# Course: 5210 Communicating Data
# Purpose: Technical Appendix of King County Food Inspection
# Author: Sakshi Madan 

# define default values for code chunks
knitr::opts_chunk$set(message = FALSE, dpi=300)

1 Loading Packages

# Clear environment
rm(list = ls(all = TRUE))

# Clear environmet of packages
if(is.null(sessionInfo()$otherPkgs) == FALSE)
  lapply(paste("package:", names(sessionInfo()$otherPkgs), sep=""),
         detach, character.only = TRUE, unload = TRUE)

# Load Packages
library(tidyverse) # used to make plots
library(here) # easier way to find file path
library(gridExtra) # used to put graphs together in the same frame
library(magrittr) # enables %<>%
library(kableExtra) # to make tables look better
library(qwraps2) # nicer summary
library(janitor) # cleaning dirty data
library(rcompanion) # to run pairwiseMedianTest function in the rcompanion package, which conducts Mood’s median test on all pairs of groups from one-way data

2 Importing database

Name Program Identifier Inspection Date Description Address City Zip Code Phone Longitude Latitude Inspection Business Name Inspection Type Inspection Score Inspection Result Inspection Closed Business Violation Type Violation Description Violation Points Business_ID Inspection_Serial_Num Violation_Record_ID Grade
11TH FRAME RESTAURANT & LOUNGE 11TH FRAME RESTAURANT & LOUNGE 10/28/08 Seating 51-150 - Risk Category III 7638 NE BOTHELL WAY KENMORE 98028
  1. 486-5555
-122.2377 47.75787 11TH FRAME RESTAURANT & LOUNGE Routine Inspection/Field Review 20 Unsatisfactory FALSE BLUE 3400 - Wiping cloths properly used, stored 5 PR0006149 DA1913312 IV0641643 1
11TH FRAME RESTAURANT & LOUNGE 11TH FRAME RESTAURANT & LOUNGE 3/14/06 Seating 51-150 - Risk Category III 7638 NE BOTHELL WAY KENMORE 98028
  1. 486-5555
-122.2377 47.75787 11TH FRAME RESTAURANT & LOUNGE Routine Inspection/Field Review 25 Unsatisfactory FALSE BLUE 3400 - Wiping cloths properly used, stored 5 PR0006149 DA1506094 IV0544191 1
12TH AVE CAFE 12TH AVE CAFE 11/16/07 Seating 13-50 - Risk Category III 775 NW GILMAN BL C-08 Issaquah 98027
  1. 397-5975
-122.0503 47.54333 12TH AVE CAFE Routine Inspection/Field Review 8 Satisfactory FALSE BLUE 3400 - Wiping cloths properly used, stored 5 PR0044084 DA1771025 IV0601455 1
12TH AVE CAFE 12TH AVE CAFE 2/5/07 Seating 13-50 - Risk Category III 775 NW GILMAN BL C-08 Issaquah 98027
  1. 397-5975
-122.0503 47.54333 12TH AVE CAFE Routine Inspection/Field Review 5 Unsatisfactory FALSE BLUE 3400 - Wiping cloths properly used, stored 5 PR0044084 DA1646621 IV0575152 1
14 CARROT CAFE 14 CARROT CAFE 4/3/06 Seating 51-150 - Risk Category III 2305 EASTLAKE AVE E Seattle 98102
  1. 324-1442
-122.3261 47.63986 14 CARROT CAFE Routine Inspection/Field Review 5 Satisfactory FALSE BLUE 3400 - Wiping cloths properly used, stored 5 PR0003061 DA1511739 IV0545210 2
14 CARROT CAFE 14 CARROT CAFE 2/9/06 Seating 51-150 - Risk Category III 2305 EASTLAKE AVE E Seattle 98102
  1. 324-1442
-122.3261 47.63986 14 CARROT CAFE Routine Inspection/Field Review 10 Satisfactory FALSE BLUE 3400 - Wiping cloths properly used, stored 5 PR0003061 DA1475214 IV0540380 2
  • About the dataset:
    • Each row in this dataset is an inspection, and if an inspection at a particular restaurant results in multiple violations, there will be multiple rows for that restaurant with the same inspection serial number
    • Data is collected from January 1st 2006 until November 13th 2019
  • First observations:
    • The data is in a tidy format
    • There are 275312 observations and 22 variables in the data set
  • Variables explanation:
    • Name: Official name of the restaurant being inspected (Need to be a factor)
    • Program Identifier: Name of the restaurant being inspected (Need to be a factor)
    • Inspection Date: Date of the food inspection (Need to be date format)
    • Description: Based on the seating number and risk categories: (Need to be a factor)
      - Risk Category I: They do not prepare food on site
      - Risk Category II: They assemble food on site, do not prepare from scratch
      - Risk Category III: They prepare food from scratch and are more complex
    • Address: Address of the restaurant being inspected (Need to be a factor)
    • City: City in which restaurant being inspected is located (Need to be a factor)
    • Zipcode: Zipcode where restaurant being inspected is located (Need to be a factor)
    • Phone: Phone number of the restaurant being inspected (Need to be a factor)
    • Longitude: Longitudinal coordinates of the restaurant site
    • Latitude: Latitudinal coordinates of the restaurant site
    • Inspection Business Name: Same as official restaurant name being inspected (Need to be a factor)
    • Inspection Type: (Need to be a factor)
      - Routine Inspection/Field Review: Scored and unannounced inspections
      - Return Inspection: Occur as needed to address violations observed during routine
      observations
      - Consultation/Education: Many restaurants receive an unscored consultation/educational visits each year
    • Inspection Score: Cumulative for all violation points for each inspection serial number(Max 400). Higher the score, more the violations occured.Scores over 35 may result in a return inspection (Need to be a Numeric)
    • Inspection Result: (Need to be a factor)
      - Multiple categories like satisfactory, unsatisfactory, complete, incomplete
    • Inspection Closed Business: (Need to be a factor)
      - TRUE: If the restaurant was closed due to not meeting minimum standards
      - FALSE: If the restaurant met minimum standards
    • Violation Type: (Need to be a factor)
      - BLUE: Not much critical violations like maintainance and sanitation issues with the restaurant
      - RED: Critical violations leading to food-borne diseases
    • Violation Description: Different types of violations like: (Need to be a factor)
      - 4100: Warewashing facilities properly installed
      - 3400: Wiping cloths properly used, stored, proper sanitizer, and more
    • Violation Points: Score for each violation (Need to be a numeric)
    • Business_ID: Identifier of the restaurant (Need to be a factor)
    • Inspection_Serial_Num: Unique number for each inspection. They can be multiple if there are more than 1 violations in one inspection. (Need to be a factor)
    • Violation_Record_ID: Identifier for each violation record (Need to be a factor)
    • Grade: These grades are calculated based on Zipcodes: (Need to be a factor)
      - 1: Excellent (When No/few red critical violations have occurred)
      - 2: Good ( When some red critical violations have occurred)
      - 3: Okay (When many red critical violations have occurred)
      - 4: Needs to improve (Either the restaurant closed within last year or restaurant needed multiple inspections to fix safety practices, this is not adjusted by zipcode)

3 Adjusting data

## 'data.frame':    274780 obs. of  23 variables:
##  $ Program_Identifier        : Factor w/ 11170 levels "\"FLEX B\"","************ DO NOT ISSUE PERMIT, SEE INSPECTOR NOTES****************",..: 8054 7443 2493 583 11140 6787 5843 5078 8315 9770 ...
##  $ Business_ID               : Factor w/ 12408 levels "PR0001008","PR0001010",..: 900 2541 2726 4102 620 1419 4389 7427 8322 1950 ...
##  $ Address                   : Factor w/ 9704 levels "1 16TH ST NE",..: 571 3586 6200 4359 6696 832 9308 982 6069 5080 ...
##  $ Phone                     : Factor w/ 7198 levels "(180) 054-21310",..: 7198 7198 3719 1727 1677 2687 5835 7155 5487 7198 ...
##  $ City                      : Factor w/ 51 levels "(NONE)","ALGONA",..: 18 7 18 40 40 23 40 23 17 22 ...
##  $ ZipCode                   : Factor w/ 89 levels "98001","98002",..: 3 10 3 63 56 24 60 23 15 22 ...
##  $ Longitude                 : num  -122 -122 -122 -122 -122 ...
##  $ Latitude                  : num  47.3 47.8 47.3 47.6 47.6 ...
##  $ Year                      : chr  "2017" "2019" "2015" "2016" ...
##  $ Month                     : chr  "04" "07" "03" "10" ...
##  $ Inspection_Type           : Factor w/ 3 levels "Consultation/Education - Field",..: 3 1 3 1 1 3 1 1 3 3 ...
##  $ Inspection_Score          : num  0 0 0 0 0 5 0 0 0 0 ...
##  $ Inspection_Result         : Factor w/ 19 levels "Baseline Data",..: 18 2 18 2 2 18 2 2 2 18 ...
##  $ Inspection_Closed_Business: Factor w/ 2 levels "FALSE","TRUE": 1 1 1 1 1 1 1 1 1 1 ...
##  $ Inspection_Serial_Num     : Factor w/ 190971 levels "DA0000LER","DA000IDQV",..: 1 2 3 4 5 6 7 8 9 10 ...
##  $ Violation_Type            : Factor w/ 3 levels "BLUE","RED","NONE": 3 3 3 3 3 1 3 3 3 3 ...
##  $ Violation_Number          : Factor w/ 55 levels "0100","0200",..: 55 55 55 55 55 38 55 55 55 55 ...
##  $ Violation_Description     : Factor w/ 76 levels "Accurate thermometer provided and used ...",..: 76 76 76 76 76 75 76 76 76 76 ...
##  $ Violation_Record_ID       : Factor w/ 156396 levels "IV000CSWF","IV000DUDZ",..: 156396 156396 156396 156396 156396 147195 156396 156396 156396 156396 ...
##  $ Violation_Points          : num  0 0 0 0 0 5 0 0 0 0 ...
##  $ Seating                   : Factor w/ 15 levels "Bakery-no seating",..: 10 12 12 13 15 12 13 13 12 15 ...
##  $ Risk_Category             : Factor w/ 3 levels "Risk Category I",..: 2 3 3 3 3 3 3 3 3 3 ...
##  $ Grade                     : Factor w/ 5 levels "1","2","3","4",..: 5 1 1 1 1 1 1 3 1 2 ...
  • About the dataset:
    • After cleaning, we now have 274780 observations and 23 variables

4 Base EDA

4.1 Uni-variate non-graphical EDA

4.1.1 Variables which do not need for us to remove duplicates based on inspection serial number

##  Violation_Type Violation_Number
##  BLUE: 73237    NONE   :118386  
##  RED : 83157    2110   : 13580  
##  NONE:118386    3400   : 13018  
##                 0600   : 12966  
##                 0200   :  9956  
##                 3300   :  8848  
##                 (Other): 98026  
##                                                    Violation_Description
##  NONE                                                         :118386   
##  Proper cold holding temperatures (greater than  45 degrees F): 15378   
##  Adequate handwashing facilities                              : 12966   
##  Warewashing facilities properly installed,...                :  8594   
##  Wiping cloths properly used, stored, proper sanitizer        :  8594   
##  Food-contact surfaces maintained, clean, sanitized           :  7747   
##  (Other)                                                      :103115   
##  Violation_Record_ID Violation_Points
##  NONE     :118386    Min.   : 0.000  
##  IV000CSWF:     1    1st Qu.: 0.000  
##  IV000DUDZ:     1    Median : 3.000  
##  IV000FITC:     1    Mean   : 4.582  
##  IV000IGTX:     1    3rd Qu.: 5.000  
##  IV000JMC4:     1    Max.   :30.000  
##  (Other)  :156389
  • Findings:
    • BLUE violations have occurred 26.65% of times. RED violations have occured 30.26% of times. No violations occurred 43.08% of times.
    • There are various types of violations occurring categorized by Violation_Number and their corresponding decriptions under Violation_Description
    • For violation points, I am going to consider median 3 as the measure of central tendency since the distribution is skewed

4.1.2 Variables which need for us to remove duplicates based on inspection serial number

inspection_data_not_dup <- inspection_data[!duplicated(inspection_data$Inspection_Serial_Num),]

inspection_data_not_dup %>% select(-Violation_Type, -Violation_Number, -Violation_Description, -Violation_Record_ID, -Violation_Points) %>% summary()
##              Program_Identifier    Business_ID    
##  SUBWAY               :   996   PR0048541:    76  
##  TACO TIME            :   931   PR0070218:    75  
##  MCDONALD'S           :   445   PR0054525:    65  
##  TACO DEL MAR         :   306   PR0012643:    64  
##  CAFFE LADRO          :   297   PR0067545:    58  
##  PCC COMMUNITY MARKETS:   274   PR0003071:    57  
##  (Other)              :187720   (Other)  :190574  
##                      Address                  Phone       
##  151 S ROYAL BROUGHAM WAY:  1769   (Missing)     : 61387  
##  15600 NE 8TH ST         :   469   (253) 796-7155:  1047  
##  6407 20TH ST E          :   406   (623) 869-3573:   594  
##  800 OCCIDENTAL AVE S    :   363   (206) 547-1222:   555  
##  2746 NE 45TH ST         :   290   (206) 652-0877:   513  
##  701 5TH AVE             :   267   (310) 604-3200:   488  
##  (Other)                 :187405   (Other)       :126385  
##           City          ZipCode         Longitude         Latitude    
##  SEATTLE    :92294   98101  :  7797   Min.   :-122.9   Min.   :47.04  
##  BELLEVUE   :12367   98104  :  7391   1st Qu.:-122.3   1st Qu.:47.47  
##  KENT       :10307   98105  :  6480   Median :-122.3   Median :47.60  
##  RENTON     : 8397   98052  :  6275   Mean   :-122.3   Mean   :47.56  
##  FEDERAL WAY: 8241   98003  :  6007   3rd Qu.:-122.2   3rd Qu.:47.66  
##  REDMOND    : 7143   98103  :  5555   Max.   :-121.1   Max.   :47.93  
##  (Other)    :52220   (Other):151464   NA's   :1        NA's   :1      
##      Year              Month          
##  Length:190969      Length:190969     
##  Class :character   Class :character  
##  Mode  :character   Mode  :character  
##                                       
##                                       
##                                       
##                                       
##                         Inspection_Type   Inspection_Score 
##  Consultation/Education - Field : 47331   Min.   :  0.000  
##  Return Inspection              :  6337   1st Qu.:  0.000  
##  Routine Inspection/Field Review:137301   Median :  0.000  
##                                           Mean   :  6.633  
##                                           3rd Qu.: 10.000  
##                                           Max.   :178.000  
##                                                            
##       Inspection_Result Inspection_Closed_Business Inspection_Serial_Num
##  Satisfactory  :92360   FALSE:190800               DA0000LER:     1     
##  Unsatisfactory:51868   TRUE :   169               DA000IDQV:     1     
##  Complete      :45302                              DA000K1RP:     1     
##  Incomplete    :  739                              DA000OF4Z:     1     
##  Not Accessible:  278                              DA000TBVH:     1     
##  Not Applicable:  205                              DA000ZCIY:     1     
##  (Other)       :  217                              (Other)  :190963     
##                      Seating                Risk_Category   
##  Seating 13-50           :48509   Risk Category I  : 15116  
##  Seating 0-12            :42058   Risk Category II : 31842  
##  Seating 51-150          :39312   Risk Category III:144011  
##  School Lunch Program    :11612                             
##  Meat/Sea Food           :10354                             
##  Grocery Store-no seating: 9398                             
##  (Other)                 :29726                             
##        Grade      
##  1        :94515  
##  2        :42504  
##  3        : 4355  
##  4        :  189  
##  (Missing):49406  
##                   
## 
  • Findings:
    • There are 10702 unique restaurants being inspected by King County for food safety
    • There are 51 cities covered by King County for Food Inspections. Few of which are Seattle, Bellevue, Kent, Renton, Federal Way, Redmond and many more
    • Almost half of the inspections 48.33% are carried out in Seattle
    • Inspections are carried out across 89 Zipcodes in King County
    • We also have coordinates available for all the restaurants being inspected
    • The data is beginning from January 2006 until mid November 2019
    • 71.9% of inspections carried out by King County are Routine/Field Reviews
    • Mean and median of inspection score are different, which means the data is skewed so we will be using median as the measure of central tendency
    • The inspection has been satisfactory 48.36% of times. The inspection has been unsatisfactory 27.16% of times. The inspection has been complete 23.72% of times.
    • The restaurants are closed 0.09% of times, which means they did not meet minimum health standards during the inspection. It is possible that they could have been reopened again.
    • Out of unique 190969 inspections, 25.4% are carried out on restaurants with Seating 13-50. 22.02% are carried out on restaurants with Seating 0-12 and 20.59% are carried out on restaurants with Seating 51-150. Remaining restaurant types are School Lunch Programs, Meat/Seafood, Grocery Stores - no seating, Seating 151-250 and few more.
    • Maximum restaurants being inspected are under Risk Category III (which prepare food from scratch - 75.41%)
    • Out of 10996 restaurants, 48.65% are graded 1, 19.46% are graded 2 and 2.27% are graded 3. We do not have grades for 29.51% of restaurants As mentioned before, these grades are calculated within the same zipcodes.

4.2 Uni-variate graphical EDA

  • Histograms and Boxplots for quantitative variables - Inspection Score and Violation Points
  • Bar graphs for factor variables

4.2.1 Inspection Score

  • The inspection score seems to be skewed towards left, thus we are going to consider median as the measure of central tendency
  • There are a lot of outliers with inspection score greater than 25

4.2.2 Violation Points

  • There are gaps in the distribution of violation points
  • Most of the inspections had 0 violation points, followed by 5 and 10

4.2.3 City

  • There are 51 cities in which inspections are carried out by King County

4.2.4 Zipcode

  • There are 89 zipcodes in which inspections are carried out by King County

4.2.5 Inspection Type

  • Maximum inspections being carried out in King County are for Inspection / Field Review, followed by Consultation and Education
  • We can look at what % of restaurants require return inspection?

4.2.6 Inspection Result

  • Most of the inspections carried out were satisfactory followed by unsatisfactory and complete
  • We will be looking at these categories from here on since we do not have a lot of data for other categories
  • What factors does the inspection result depend on? What are the range of inspection scores in various categories for inspection result?

4.2.7 Inspection Closed Business

  • Most of the times the restaurant did not close
  • What caused a restaurant to close?

4.2.8 Violation Type

  • There are more RED violations than BLUE.
  • Also, restaurants have not violated maximum number of times

4.2.9 Violation Number

  • We can look at which violation numbers are occurring the most? Are there patterns of violation numbers during different months?
  • Same distribution for violation description

4.2.10 Seating

  • Most of the restaurants being inspected for food safety in King County are with Seating 13 - 50, followed by Seating 51 - 150, followed by Seating 0 - 12
  • Does the violations vary by Seating types?
  • Are the inspection scores higher for more seating restaurants?

4.2.11 Risk Category

  • Maximum restaurants being inspected for food safety fall under Risk Category III which means they prepare food from scratch

4.2.12 Grade

  • Most of the restaurants are graded 1 by county
  • We have a lot of missing data for grades

4.2.13 Findings

  • There are more of Red violations than blue
  • Almost half of the inspections are carried out in Seattle
  • Most of the inspections are routine and field reviews

4.2.14 Questions

  • Does inspection score varies with Cities?
  • Does violation points distribution stay the same across Cities?
  • What is the relation between inspection result and inspection score?
  • Is there any sepcific type of violation ocurring in particular area or particular month?
  • How many restaurants need return inspection?
  • How are restaurants performing over time?
  • What caused the restaurants to close?
  • Does more Seatings increase violations/inspection score?
  • What caused the restaurant to be graded 1?

4.3 Multi-variate non-graphical analysis

4.3.1 Inspection Type x Inspection Result

Inspection_Type Complete Satisfactory Unsatisfactory
Consultation/Education - Field 92.4% (43757) 6.4% (3008) 0.2% (74)
Return Inspection 13.1% (830) 58.6% (3715) 27.0% (1710)
Routine Inspection/Field Review 0.5% (715) 62.4% (85637) 36.5% (50084)
Total 23.7% (45302) 48.4% (92360) 27.2% (51868)
  • Routine inspections have mostly satisfactory results followed by unsatisfactory
  • Consultation/Education inspections have mostly results as ‘Complete’
  • Return inspections have mostly been satisfactory follwed by unsatisfactory
  • What causes a return inspection to be unsatisfactory?
  • How many restaurants get return inspections / unsatisfactory results every year?

4.3.2 Inspection Type x Closed Business

inspection_data_not_dup %>% 
  tabyl(Inspection_Type, Inspection_Closed_Business) %>% 
  adorn_totals(where = c("row", "col")) %>% 
  adorn_percentages("row") %>%
  adorn_pct_formatting() %>%
  adorn_ns() %>%
  select(c(1,2,3)) %>%
  kable()%>% kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = F)
Inspection_Type FALSE TRUE
Consultation/Education - Field 100.0% (47322) 0.0% (9)
Return Inspection 99.7% (6315) 0.3% (22)
Routine Inspection/Field Review 99.9% (137163) 0.1% (138)
Total 99.9% (190800) 0.1% (169)
  • It looks like restaurants are three times more likely to be closed in return inspection than routine inspection

4.3.3 Inspection Result x Closed Business

Inspection_Result FALSE TRUE
Complete 100.0% (45295) 0.0% (7)
Satisfactory 100.0% (92357) 0.0% (3)
Unsatisfactory 99.7% (51715) 0.3% (153)
Total 99.9% (190800) 0.1% (169)
  • As expected, 91% of the restaurants closed had Unsatisfactory inspections

4.3.4 Seating x Inspection Result

Complete Satisfactory Unsatisfactory Total
35.9% (1278) 51.2% (1822) 11.9% (424) 100.0% (3561)
2.0% (2) 81.0% (81) 14.0% (14) 100.0% (100)
25.2% (478) 55.6% (1056) 15.4% (293) 100.0% (1898)
  • (0) </td>
  • (0) </td>
  • (0) </td>
100.0% (0)
8.7% (816) 68.7% (6457) 22.2% (2086) 100.0% (9398)
3.2% (29) 71.0% (648) 24.6% (225) 100.0% (913)
22.5% (2334) 54.6% (5649) 22.7% (2352) 100.0% (10354)
17.2% (760) 53.0% (2346) 27.8% (1232) 100.0% (4426)
19.3% (1316) 61.9% (4222) 15.8% (1077) 100.0% (6820)
6.4% (740) 83.6% (9709) 9.4% (1088) 100.0% (11612)
25.4% (1303) 40.1% (2056) 33.8% (1733) 100.0% (5130)
25.9% (10883) 48.5% (20383) 25.1% (10536) 100.0% (42058)
27.4% (13290) 41.3% (20040) 30.6% (14868) 100.0% (48509)
25.7% (1768) 37.7% (2590) 36.1% (2486) 100.0% (6878)
26.2% (10305) 38.9% (15301) 34.2% (13454) 100.0% (39312)
23.7% (45302) 48.4% (92360) 27.2% (51868) 100.0% (190969)
  • As the Seating increases, there is more percentage of unsatisfactory results within the group
  • May be small restaurants have better quality control
  • As mentioned before, we are only looking at Satisfactory/Unsatisfactory and Complete inspection results
  • 4.3.5 Seating x Inspection Type

    Seating Consultation/Education - Field Return Inspection Routine Inspection/Field Review
    Bakery-no seating 39.4% (1402) 0.6% (23) 60.0% (2136)
    Bed and Breakfast 2.0% (2) 1.0% (1) 97.0% (97)
    Caterer 25.7% (487) 1.2% (23) 73.1% (1388)
    Commissary for Mobile FSE
    • (0) </td>
    •  (0) </td>
    Grocery Store-no seating 9.9% (932) 0.6% (57) 89.5% (8409)
    Limited Food Services - no permanent plumbing 2.6% (24) 2.0% (18) 95.4% (871)
    Meat/Sea Food 29.5% (3058) 0.5% (49) 70.0% (7247)
    Mobile Food Unit 20.3% (900) 4.6% (203) 75.1% (3323)
    Non-Profit Institution 20.1% (1374) 0.8% (52) 79.1% (5394)
    School Lunch Program 6.2% (716) 0.3% (40) 93.5% (10856)
    Seating > 250 25.6% (1314) 4.9% (252) 69.5% (3564)
    Seating 0-12 27.1% (11388) 2.4% (1029) 70.5% (29641)
    Seating 13-50 27.9% (13517) 4.2% (2039) 67.9% (32953)
    Seating 151-250 26.0% (1788) 5.5% (375) 68.6% (4715)
    Seating 51-150 26.5% (10429) 5.5% (2176) 67.9% (26707)
    Total 24.8% (47331) 3.3% (6337) 71.9% (137301)
  • Again, restaurants with more seating have more requirement of return inspections
  • 4.3.6 Seating x Inspection Closed Business

    Seating FALSE TRUE
    Bakery-no seating 100.0% (3561) 0.0% (0)
    Bed and Breakfast 100.0% (100) 0.0% (0)
    Caterer 99.9% (1897) 0.1% (1)
    Commissary for Mobile FSE
    •  (0) </td>
    Grocery Store-no seating 100.0% (9398) 0.0% (0)
    Limited Food Services - no permanent plumbing 99.8% (911) 0.2% (2)
    Meat/Sea Food 100.0% (10350) 0.0% (4)
    Mobile Food Unit 99.2% (4391) 0.8% (35)
    Non-Profit Institution 100.0% (6818) 0.0% (2)
    School Lunch Program 100.0% (11612) 0.0% (0)
    Seating > 250 99.9% (5123) 0.1% (7)
    Seating 0-12 100.0% (42043) 0.0% (15)
    Seating 13-50 99.9% (48463) 0.1% (46)
    Seating 151-250 99.9% (6872) 0.1% (6)
    Seating 51-150 99.9% (39261) 0.1% (51)
    Total 99.9% (190800) 0.1% (169)
  • Looks like mobile food units get closed a lot
  • 4.3.7 Seating x Risk Category

    Seating Risk Category I Risk Category II Risk Category III
    Bakery-no seating 0.4% (14) 94.4% (3361) 5.2% (186)
    Bed and Breakfast 100.0% (100) 0.0% (0) 0.0% (0)
    Caterer 1.6% (31) 3.4% (65) 94.9% (1802)
    Commissary for Mobile FSE
    • (0) </td>
    • (0) </td>
    •  (0) </td>
    Grocery Store-no seating 80.6% (7578) 19.4% (1820) 0.0% (0)
    Limited Food Services - no permanent plumbing 100.0% (913) 0.0% (0) 0.0% (0)
    Meat/Sea Food 0.0% (0) 0.0% (0) 100.0% (10354)
    Mobile Food Unit 12.9% (570) 8.4% (373) 78.7% (3483)
    Non-Profit Institution 11.3% (770) 8.8% (601) 79.9% (5449)
    School Lunch Program 0.0% (0) 100.0% (11612) 0.0% (0)
    Seating > 250 0.9% (48) 0.0% (0) 99.1% (5082)
    Seating 0-12 8.1% (3387) 15.5% (6530) 76.4% (32141)
    Seating 13-50 2.4% (1161) 13.7% (6658) 83.9% (40690)
    Seating 151-250 0.7% (50) 0.2% (11) 99.1% (6817)
    Seating 51-150 1.3% (494) 2.1% (811) 96.7% (38007)
    Total 7.9% (15116) 16.7% (31842) 75.4% (144011)
  • Grocery Stores form more than half of the Risk Category I restaurants
  • Risk Category II are dominated by restaurants with Seating 0-12 and 13-50
  • 4.3.8 Inspection Result x Violation Type

    Inspection_Result BLUE RED NONE Total
    Complete 0.5% (219) 0.6% (286) 98.9% (45056) 100.0% (45561)
    Satisfactory 28.5% (28897) 1.6% (1625) 69.9% (70929) 100.0% (101451)
    Unsatisfactory 34.9% (44061) 64.3% (81155) 0.8% (1050) 100.0% (126266)
    • Inspection results are unsatisfactory when there are RED violations mostly
    • Inspection results are complete when there are no violations mostly

    4.3.9 Seating x Violation Type

    Seating BLUE RED NONE
    Bakery-no seating 23.0% (963) 13.2% (554) 63.7% (2666)
    Bed and Breakfast 9.7% (11) 17.7% (20) 72.6% (82)
    Caterer 20.3% (459) 17.8% (402) 61.9% (1399)
    Commissary for Mobile FSE
    • (0) </td>
    • (0) </td>
    •  (0) </td>
    Grocery Store-no seating 16.9% (1917) 25.1% (2846) 57.9% (6554)
    Limited Food Services - no permanent plumbing 23.4% (272) 27.9% (324) 48.8% (567)
    Meat/Sea Food 22.4% (2987) 26.0% (3462) 51.6% (6875)
    Mobile Food Unit 15.7% (936) 34.8% (2078) 49.5% (2958)
    Non-Profit Institution 18.7% (1479) 18.1% (1430) 63.2% (5006)
    School Lunch Program 12.8% (1572) 10.2% (1254) 76.9% (9418)
    Seating > 250 30.4% (2542) 35.8% (2995) 33.8% (2831)
    Seating 0-12 22.7% (12624) 28.5% (15858) 48.8% (27169)
    Seating 13-50 29.9% (22313) 32.7% (24434) 37.5% (28001)
    Seating 151-250 31.6% (3687) 37.5% (4366) 30.9% (3603)
    Seating 51-150 32.6% (21475) 35.1% (23134) 32.3% (21257)
    Total 26.7% (73237) 30.3% (83157) 43.1% (118386)
  • It appears that as the seating increases, the proportion of red violations increase
  • 4.3.10 Violation Type x Risk Category

    Violation_Type Risk Category I Risk Category II Risk Category III
    BLUE 5.1% (3744) 8.3% (6105) 86.6% (63388)
    RED 5.2% (4285) 6.3% (5280) 88.5% (73592)
    NONE 8.7% (10286) 20.6% (24420) 70.7% (83680)
    Total 6.7% (18315) 13.0% (35805) 80.3% (220660)
    • Restaurants under Risk Category III have almost similar percentage of red and blue violations

    4.3.11 City x Violation Type

    City BLUE RED NONE
    BELLEVUE 26.0% (5130) 38.3% (7551) 35.7% (7043)
    FEDERAL WAY 26.1% (3027) 31.1% (3601) 42.8% (4956)
    KENT 22.5% (3072) 26.5% (3616) 51.1% (6978)
    RENTON 24.2% (2854) 28.6% (3374) 47.2% (5560)
    SEATTLE 29.0% (39506) 30.5% (41539) 40.6% (55368)
    • We looked at the top 5 cities with maximum number of restaurants and realized that Bellevue has more percentage of Red Violations than None which is the opposite of others
    • Does this pattern of Bellevue remain the same across the years?
    • Does this pattern of other cities remain the same across the years?

    4.3.12 Correlation Table

    ##                  Inspection_Score    points
    ## Inspection_Score        1.0000000 0.9955811
    ## points                  0.9955811 1.0000000
    • We can see that inspection score is very closely related to violation points because every score is a sum of independent violation points grouped by inspection serial number

    • Findings and Questions
      • We found out that restaurants were closed on return inspections
      • As the Seating increases, proportion of red violations and return inspections increase
      • Inspection Score and Violation Points are very strongly related obviously
      • When looking at the top 5 cities with most restaurants in King County, we observed that Bellevue has more of red violations than blue
      • Does the trend of Red/Blue violations remain the same for cities across the years?

    4.4 Multi-variate graphical analysis

    4.4.1 Number of inspections every year

    • Excluded 2019 data because its not for the complete year
    • The number of inspections have been increasing every year except for 2015 where there was a drop
    • The number of inspections in 2015 declined by 3.85% as compared to 2014
    • The number of inspections in 2017 increased by 14.33% as compared to 2016 which further increased by 10.97% in 2018

    4.4.2 Number of unique restaurants being inspected every year

    • Number of unique restaurants being inspected increased by 5.85% in 2015 as compared to 2014 but the decline of number of inspections could mean there was a decline in number of inspections per restaurant
    • On the contrary in 2017, the rise in number of unique restaurants being inspected was 12.38% but the total number of inspections increased at a much higher rate, which could imply that there were increase in number of inspections per restaurant

    4.4.3 Number of inspections per restaurant

    • As mentioned above, we can see a clear decline in the number of inspections per restaurant in 2015, continued to 2016 as well
    • The number of inspections per restaurant increased to 2 in 2017
    • There is a clear decline in number of inspections per restaurant from 2006 to 2018

    4.4.4 Percentage of restaurants requiring return inspection

    • Included 2019 as well because we are calculating percentages
    • In 2014, 8.19% of restaurants needed return inspection which was a huge jump from 2013. 2014 was the year when there was a major food borne illess outbreak. The percentage increased to 8.87% in 2015
    • It started to decline in 2016 and has been since then

    4.4.5 Number of violations per restaurant every year

    • There was a hugh jump in 2014(illness outbreak), the number of violations per restaurant increased to a little more than 2
    • In 2018, the number of violations per restaurant declined to approximately 1.55

    4.4.6 Percentage of restaurants with violation

    • Again we have 2019 here because we are calculating percentage, not the absolutes
    • The percentage of restaurants violating increased to 62% in 2014 and then started to decline in 2015
    • We can see there is a sharp decline in 2019 which is 62%

    4.4.7 Percentage of restaurants with no violation

    • The percentage of businesses in King County that have no violation increased in 2018 from 43.75% to 45.77%
    • The percentage has further increased to 49.97% in 2019
    • Has this percentage improved across major 5 cities?

    4.4.8 Percentage of restaurants with red violations

    • The percentage of restaurant with red violations were really high in 2014 and 2015 which were 49% and 48.11% respectively
    • They started to decline in 2016
    • Has this percentage improved across major 5 cities?

    4.4.9 Percentage of restaurants with blue violations

    • The percentage of restaurants with blue violations declined to 12% in 2015
    • It started to increase in 2016 but the percentage difference is not very high

    4.4.10 Percentage of restaurants with no violation across 5 major cities

    city_unique_business_inspection_year <- inspection_data_not_dup %>% 
      filter(City %in% c("BELLEVUE","KENT","FEDERAL WAY","SEATTLE","RENTON")) %>% 
      group_by(Year, City) %>% 
      summarise(count_businesses = n_distinct(Business_ID))
    
    city_none_count <- inspection_data %>% 
      filter(City %in% c("BELLEVUE","KENT","FEDERAL WAY","SEATTLE","RENTON")) %>% 
      group_by(Year, City, Business_ID) %>% 
      summarise(count = length(which(Violation_Type != "NONE"))) %>% 
      filter(count == 0) %>% 
      group_by(Year, City) %>% 
      summarise(none = n())
    
    merged_none <- merge(city_unique_business_inspection_year, city_none_count, by = c('Year','City'))
    merged_none$rate <- merged_none$none/merged_none$count_businesses
    
    merged_none %>% 
      ggplot(mapping = aes(y = rate, x = Year, group = City)) +
      geom_line() +
      facet_wrap(~City)

    • All 5 cities are responding are improved with the new rating system in 2017 in terms of percentage of non-violating restaurants
    • Seattle seems to be consistent after that as well

    4.4.11 Percentage of restaurants with red violation across 5 major cities

    city_red_count_total <- inspection_data %>% 
      filter(City %in% c("BELLEVUE","KENT","FEDERAL WAY","SEATTLE","RENTON")) %>% 
      group_by(Year, City, Business_ID) %>% 
      summarise(count = length(which(Violation_Type == "RED"))) %>% 
      filter(count != 0) 
    
    city_red_count <- city_red_count_total %>% 
      group_by(Year, City) %>% 
      summarise(red = n())
    
    merged_red <- merge(city_unique_business_inspection_year, city_red_count, by = c('Year','City'))
    merged_red$rate <- merged_red$red/merged_red$count_businesses
    
    
    merged_red %>% 
      ggplot(mapping = aes(y = rate, x = Year, group = City)) +
      geom_line() +
      facet_wrap(~City)

    • Other than Renton, there was a decline in percentage of red violation restaurants from 2016 to 2017
    • Only Seattle seems to be follow the trend after that as well

    4.4.12 Percentage of restaurants with blue violation across 5 major cities

    city_blue_count_total <- inspection_data %>% 
      filter(City %in% c("BELLEVUE","KENT","FEDERAL WAY","SEATTLE","RENTON")) %>%
      group_by(Year, City, Business_ID) %>% 
      summarise(count = length(which(Violation_Type == "BLUE"))) %>%
      filter(count != 0)
    
    city_red_count_total <- city_red_count_total %>% select(-4) 
    city_blue_count_total <- city_blue_count_total %>% select(-4)
    intersect <- inner_join(city_red_count_total, city_blue_count_total)
    city_blue_count <- anti_join(city_blue_count_total, intersect, by = c('Year','City','Business_ID'))
    city_blue_count <- city_blue_count %>%
                  group_by(Year, City) %>%
                  summarise(blue = n())
    
    merged_blue <- merge(city_unique_business_inspection_year, city_blue_count, by = c('Year','City'))
    merged_blue$rate <- merged_blue$blue/merged_blue$count_businesses
    
    
    merged_blue %>% 
      ggplot(mapping = aes(y = rate, x = Year, group = City)) +
      geom_line() +
      facet_wrap(~City)

    • There is no major impact on blue violation restaurants across 5 major cities from 2016 to 2017
    • Federal way seems to be performing the worst

    4.4.13 Monthly pattern of red violations

    • It appears that red violations increase at the beginning of the year, comes down in summer and then increase during winter again
    • For some reason, December 2008 had very few red violations
    • This is a pattern to be analyzed in future as how does the seasons affect violations?

    4.4.14 Pattern of violation numbers every month

    • These are the top 3 violation types ocurring every month
    • 200 (Food worker cards not current), 600 (Adequate handwashing) and 2110 (Proper cold holding tempearature) are red violations
    • 3400 (Wiping clothes properly used) is a blue violation
    • Violation number 0200 is more common in January and February

    4.4.15 Median of inspection scores for violating businesses

    • 2014 food illness outbreak has something to do with the increase of inspection score?
    • The median of inspection scores decline drastically from 2016 to 2017
    • This might be the impact of the new rating system introduced in 2017
    • Is the same pattern across the 5 major cities?

    4.4.16 Median of inspection scores for violating businesses across 5 major cities

    • Bellevue did not have a decline in median inspection score since 2008
    • Seattle is the only city where median inspection score declined in 2017
    • Median inspection score in Renton declined in 2018

    4.4.17 Inspection scores across Seating types

    • There are differences in the inter quartile range for inspection scores for various seating types

    4.4.18 Inspection scores across Risk Categories

    • Restaurants with Risk Category III have higher interquartile range for inspection scores

    4.4.19 Inspection scores across Cities

    • Bellevue, Seattle and Federal Way have wider interquartile range for inspection score
    • How does this vary across the years?

    • Findings
    • In the new system introduced in 2017, number of inspections are increasing at a higher rate as compared to increase in the number of restaurants
    • Percentage of restaurants requiring return inspection were really high in 2014 and 2015 and started to decline in 2016
    • In 2014, there were a high number of violations even though the increase in number of restaurants grew at the regular rate which implies there were more violations per restaurant in 2014
    • With the enforcement of new rating system, the number of restaurants with no violations increased much faster
    • There was a huge increase in red violations in 2014 which only started to reduce since 2017
    • After the introduction of the new rating system, number of restaurants with 0 critical violations increased from 55% in 2016 to 57% in 2017. It further increased to 61% in 2018.
    • Number of red violations follow a pattern throughout the year. Spring has the maximum number of red violations followed by winter
    • The most common types of violations occurring are 200,600,2110 (Red) and 3400 (Blue)
    • Inspection Score shoot up really high in 2014 and started to decline significantly after 2017 since the introduction of the new rating system
    • The median inspection score of 5 major cities is closer to zero, does this pattern change after the introduction of the new rating system?
    • Median Inspection Score never declined in Bellevue
    • Seattle is the only city where median inspection score declined in 2017

    5 Testing statistical significance

    5.1 The percentage of restaurants with no violations/red violations/blue violations have changed since the introduction of new rating system in 2017

    We are going to perform a chi square test where we will compare the 2017 data (proportion of restaurants with none/red/blue violations) against the proportion of restaurants with none/red/blue violations which happened in 2016
    Note: Restaurants which have both red and blue violations, have been categorized under restaurants with red violations

    ## 
    ##  Pearson's Chi-squared test
    ## 
    ## data:  test_data and exp_prob
    ## X-squared = 6, df = 4, p-value = 0.1991
    • From this test, we can conclude with 80% confidence that there is a significant difference between proportions of businesses having none, red and blue violations in 2017 as compared to 2016.
    merged_violations %>%
            ggplot(mapping = aes(x = Year, y = rate, fill = factor(type, levels = c('blue','red','none')))) +
            geom_bar(position = position_stack(), stat = "identity", width = 0.7) +
            geom_text(aes(label = label), position = position_stack(vjust = 0.5), size = 3, color = 'black') +
            coord_flip() +
            scale_fill_manual(values = c('steelblue4','red4','snow4'), name = "Violation Type:", labels = c("Blue","Red","None")) +
            theme(legend.position = 'bottom', axis.title.y = element_blank(), plot.title = element_text(size = 11), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank(), axis.line = element_line(color = "black"), axis.text.x = element_blank(), axis.ticks.x = element_blank(), legend.title = element_text(size = 8), legend.text = element_text(size = 8), legend.key.size = unit(0.8,"line"),legend.margin=margin(0,0,0,0),legend.box.margin=margin(-3,-3,-3,-3)) +
            labs(title = "New rating system is leading to healthier restaurants", y = "") +
            guides(fill = guide_legend(reverse = TRUE))

    ggsave('No_Violations.png')
    • For the years 2007, 2008 and 2010, the percentage is not totalling to 100% because of rounding off, for the exact percentages, please refer to the table below:
    Year rate.none rate.red rate.blue total
    2019 49.97365 34.75931 15.26704 100
    2018 45.76536 39.04464 15.19000 100
    2017 43.75270 42.85560 13.39170 100
    2016 42.80335 44.79534 12.40131 100
    2015 40.37877 48.10617 11.51507 100
    2014 38.32309 49.03424 12.64267 100
    2013 42.27461 43.58076 14.14463 100
    2012 41.46676 44.58533 13.94791 100
    2011 42.73392 44.15901 13.10707 100
    2010 39.42171 46.34494 14.23335 100
    2009 42.11577 41.25083 16.63340 100
    2008 40.72029 44.60984 14.66987 100
    2007 36.55636 46.84592 16.59772 100
    2006 37.02451 47.39363 15.58185 100

    5.2 The percentage of restaurants with no violations/red violations/blue violations have changed since the introduction of new rating system in 2017 across 5 major cities

    To test that, we will perform a similar chi-square test for Seattle, Bellevue, Federal Way, Kent, Redmond individually

    SEATTLE

    ## 
    ##  Pearson's Chi-squared test
    ## 
    ## data:  test_data_seattle and exp_prob_seattle
    ## X-squared = 6, df = 4, p-value = 0.1991

    BELLEVUE

    ## 
    ##  Pearson's Chi-squared test
    ## 
    ## data:  test_data_bell and exp_prob_bell
    ## X-squared = 6, df = 4, p-value = 0.1991

    FEDERAL WAY

    ## 
    ##  Pearson's Chi-squared test
    ## 
    ## data:  test_data_fed and exp_prob_fed
    ## X-squared = 6, df = 4, p-value = 0.1991

    KENT

    ## 
    ##  Pearson's Chi-squared test
    ## 
    ## data:  test_data_kent and exp_prob_kent
    ## X-squared = 6, df = 4, p-value = 0.1991

    RENTON

    ## 
    ##  Pearson's Chi-squared test
    ## 
    ## data:  exp_prob_renton and exp_prob_renton
    ## X-squared = 6, df = 4, p-value = 0.1991

    From these tests, we can conclude with 80% confidence that there is a significant difference between proportions of restaurants having none, red and blue violations in 2017 as compared to 2016 for all major 5 cities - Seattle, Bellevue, Federal Way, Kent and Redmond.

    subtitle = paste0("In Seattle, restaurants with no violations increased to ",round(merged_none[60,5]*100), "%, ",round(merged_none[65,5]*100), "% and ",round(merged_none[70,5]*100), "% in 2017, 2018 and 2019, respectively") 
    
    merged_none %>% 
      filter(City %in% c("BELLEVUE","KENT","FEDERAL WAY","SEATTLE","RENTON")) %>% 
      ggplot(mapping = aes(y = rate*100, x = Year, group = City, color = City, alpha = City, size = City)) +
      geom_line() +
      labs(title = "Seattle is the only city with consistent growing percentage of non-violating restaurants since the \nintroduction of new system in January 2017", x = "", y = "Percentage of non-violating restaurants", subtitle = subtitle) +
      scale_alpha_manual(values = c(0.4,0.4,0.4,0.4,0.8)) +
      scale_size_manual(values = c(1,1,1,1,3)) +
      scale_color_manual(values = c("darkorange3","cadetblue","purple4","yellow4","grey25")) +
      scale_y_continuous(labels = function(x) paste0(x, '%')) +
      theme(plot.title = element_text(size = 11), plot.subtitle = element_text(size = 9), axis.title = element_text(size = 9), legend.position = "bottom", legend.title = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank(), axis.line = element_line(color = "black")) 

    ggsave('Seattle_no_violation.png')

    5.3 The median inspection score of violating restaurants have declined since the introduction of new rating system in 2017

    As we saw earlier in this document since inspection score is a skewed measure we should use the median instead of the mean. To test if the medians are different we will utilize the Mood’s median test.
    Note: For testing the significance, I have used the data since 2014 because that is when food borne illness outbreak happened which led to the idea of the new rating system

    2014 2015 2016 2017 2018 2019
    2014 1.0000000 0.36600 1.000000 0.0005432 0.00000 0.00000
    2015 0.3660000 1.00000 0.090960 0.0000000 0.00000 0.00000
    2016 1.0000000 0.09096 1.000000 0.0000390 0.00000 0.00000
    2017 0.0005432 0.00000 0.000039 1.0000000 0.00000 0.00000
    2018 0.0000000 0.00000 0.000000 0.0000000 1.00000 0.01123
    2019 0.0000000 0.00000 0.000000 0.0000000 0.01123 1.00000
    • We can conclude (at 95% confidence level) that median inspection scores in 2014, 2015 and 2016 are statistically different from 2017, 2018 and 2019 after the introduction of new rating system in 2017

    5.4 The median inspection score of violating restaurants declined only in Seattle & Renton since the introduction of new rating system in 2017

    As we saw earlier in this document since inspection score is a skewed measure we should use the median instead of the mean. To test if the medians are different we will utilize the Mood’s median test.
    Note: For testing the significance, I have used the data since 2014 because that is when food borne illness outbreak happened which led to the idea of the new rating system

    SEATTLE
    2014 2015 2016 2017 2018 2019
    2014 1.0000000 1.00000 0.81260 0.0000386 0.0000000 0.00000
    2015 1.0000000 1.00000 0.01061 0.0000000 0.0000000 0.00000
    2016 0.8126000 0.01061 1.00000 0.0279400 0.0000000 0.00000
    2017 0.0000386 0.00000 0.02794 1.0000000 0.0000033 0.00000
    2018 0.0000000 0.00000 0.00000 0.0000033 1.0000000 0.02204
    2019 0.0000000 0.00000 0.00000 0.0000000 0.0220400 1.00000
    BELLEVUE
    2014 2015 2016 2017 2018 2019
    2014 1.0000 1.0000 1.00000 1 1.0000 0.29850
    2015 1.0000 1.0000 1.00000 1 0.6549 0.07430
    2016 1.0000 1.0000 1.00000 1 0.3742 0.03148
    2017 1.0000 1.0000 1.00000 1 1.0000 1.00000
    2018 1.0000 0.6549 0.37420 1 1.0000 1.00000
    2019 0.2985 0.0743 0.03148 1 1.0000 1.00000
    FEDERAL WAY
    2014 2015 2016 2017 2018 2019
    2014 1 1.0000 1.0000 1 1.0000 1.0000
    2015 1 1.0000 1.0000 1 0.6810 0.0411
    2016 1 1.0000 1.0000 1 0.4962 0.0216
    2017 1 1.0000 1.0000 1 1.0000 1.0000
    2018 1 0.6810 0.4962 1 1.0000 1.0000
    2019 1 0.0411 0.0216 1 1.0000 1.0000
    KENT
    2014 2015 2016 2017 2018 2019
    2014 1 1.0000 1 1 1 1.0000
    2015 1 1.0000 1 1 1 0.9642
    2016 1 1.0000 1 1 1 1.0000
    2017 1 1.0000 1 1 1 1.0000
    2018 1 1.0000 1 1 1 1.0000
    2019 1 0.9642 1 1 1 1.0000
    RENTON
    2014 2015 2016 2017 2018 2019
    2014 1.00000 1.00000 1.0000000 1.000000 0.0215700 0.8436000
    2015 1.00000 1.00000 1.0000000 1.000000 0.0215700 0.8370000
    2016 1.00000 1.00000 1.0000000 1.000000 0.0000006 0.0004053
    2017 1.00000 1.00000 1.0000000 1.000000 0.0000530 0.0186200
    2018 0.02157 0.02157 0.0000006 0.000053 1.0000000 1.0000000
    2019 0.84360 0.83700 0.0004053 0.018620 1.0000000 1.0000000
    • We can conclude (at 95% confidence level) that median inspection scores in 2014, 2015 and 2016 are statistically different from 2017, 2018 and 2019 after the introduction of new rating system in 2017 only in Seattle
    #Citywise median inspection score
    
    median_inspection_score_cities <- inspection_data_not_dup %>% 
      filter(City %in% c("BELLEVUE","KENT","FEDERAL WAY","SEATTLE","RENTON")) %>% 
      filter(Inspection_Score != 0) %>% 
      group_by(Year, City) %>% 
      summarise(score = median(Inspection_Score))
    
    subtitle = paste0("Median inspection score of Bellevue has been ", median_inspection_score_cities[66,3], " in 2018 and 2019 when the other cities were at ", median_inspection_score_cities[70,3])
    
      
     median_inspection_score_cities %>% 
      ggplot(mapping = aes(x = Year, y = score, group = City, color = City, alpha = City, size = City)) + 
      geom_line() +
      labs(title = "Median Inspection score of all the cities is now the same except Bellevue", subtitle = subtitle, y = "Median Inspection Score") +
      scale_alpha_manual(values = c(0.6,0.4,0.4,0.4,0.6)) +
      scale_size_manual(values = c(3,2,1,1,1)) +
      scale_color_manual(values = c("darkorange3","cadetblue","purple4","yellow4","grey25")) +
      theme(plot.title = element_text(size = 11), plot.subtitle = element_text(size = 9), axis.title = element_text(size = 9), legend.position = "bottom",panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank(), axis.line = element_line(color = "black"), legend.title = element_blank()) 

    ggsave('inspection_score_cities.png') 
    LS0tCnRpdGxlOiAiS2luZyBDb3VudHkgRm9vZCBJbnNwZWN0aW9uIgpkZXNjcmlwdGlvbjogfAogICAgVGVjaG5pY2FsIEFwcGVuZGl4LgphdXRob3I6CiAgLSBuYW1lOiBTYWtzaGkgTWFkYW4gCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OiAKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgZGZfcHJpbnQ6IGthYmxlCiAgICBrZWVwX21kOiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDQKICAgIHRvY19mbG9hdDogeWVzCmVkaXRvcl9vcHRpb25zOiAKICBjaHVua19vdXRwdXRfdHlwZTogY29uc29sZQotLS0KCmBgYHtyIG9wdGlvbnN9CiMgQ291cnNlOiA1MjEwIENvbW11bmljYXRpbmcgRGF0YQojIFB1cnBvc2U6IFRlY2huaWNhbCBBcHBlbmRpeCBvZiBLaW5nIENvdW50eSBGb29kIEluc3BlY3Rpb24KIyBBdXRob3I6IFNha3NoaSBNYWRhbiAKCiMgZGVmaW5lIGRlZmF1bHQgdmFsdWVzIGZvciBjb2RlIGNodW5rcwprbml0cjo6b3B0c19jaHVuayRzZXQobWVzc2FnZSA9IEZBTFNFLCBkcGk9MzAwKQoKYGBgCgojIExvYWRpbmcgUGFja2FnZXMKYGBge3Igc2V0dXAsIHdhcm5pbmcgPSBGQUxTRX0KIyBDbGVhciBlbnZpcm9ubWVudApybShsaXN0ID0gbHMoYWxsID0gVFJVRSkpCgojIENsZWFyIGVudmlyb25tZXQgb2YgcGFja2FnZXMKaWYoaXMubnVsbChzZXNzaW9uSW5mbygpJG90aGVyUGtncykgPT0gRkFMU0UpCiAgbGFwcGx5KHBhc3RlKCJwYWNrYWdlOiIsIG5hbWVzKHNlc3Npb25JbmZvKCkkb3RoZXJQa2dzKSwgc2VwPSIiKSwKICAgICAgICAgZGV0YWNoLCBjaGFyYWN0ZXIub25seSA9IFRSVUUsIHVubG9hZCA9IFRSVUUpCgojIExvYWQgUGFja2FnZXMKbGlicmFyeSh0aWR5dmVyc2UpICMgdXNlZCB0byBtYWtlIHBsb3RzCmxpYnJhcnkoaGVyZSkgIyBlYXNpZXIgd2F5IHRvIGZpbmQgZmlsZSBwYXRoCmxpYnJhcnkoZ3JpZEV4dHJhKSAjIHVzZWQgdG8gcHV0IGdyYXBocyB0b2dldGhlciBpbiB0aGUgc2FtZSBmcmFtZQpsaWJyYXJ5KG1hZ3JpdHRyKSAjIGVuYWJsZXMgJTw+JQpsaWJyYXJ5KGthYmxlRXh0cmEpICMgdG8gbWFrZSB0YWJsZXMgbG9vayBiZXR0ZXIKbGlicmFyeShxd3JhcHMyKSAjIG5pY2VyIHN1bW1hcnkKbGlicmFyeShqYW5pdG9yKSAjIGNsZWFuaW5nIGRpcnR5IGRhdGEKbGlicmFyeShyY29tcGFuaW9uKSAjIHRvIHJ1biBwYWlyd2lzZU1lZGlhblRlc3QgZnVuY3Rpb24gaW4gdGhlIHJjb21wYW5pb24gcGFja2FnZSwgd2hpY2ggY29uZHVjdHMgTW9vZOKAmXMgbWVkaWFuIHRlc3Qgb24gYWxsIHBhaXJzIG9mIGdyb3VwcyBmcm9tIG9uZS13YXkgZGF0YQpgYGAKCiMgSW1wb3J0aW5nIGRhdGFiYXNlCmBgYHtyIGltcG9ydGluZ19kYiwgd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KaW5zcGVjdGlvbl9kYXRhIDwtIHJlYWRfY3N2KGhlcmUoJ0Zvb2RfRXN0YWJsaXNobWVudF9JbnNwZWN0aW9uX0RhdGEuY3N2JykpCgppbnNwZWN0aW9uX2RhdGEgICU+JSBoZWFkKCkgJT4lIGthYmxlKCkgJT4lIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRikgJT4lIHNjcm9sbF9ib3god2lkdGggPSAiMTAwJSIsIGhlaWdodCA9ICI2MDBweCIpCgpgYGAKCisgX19BYm91dCB0aGUgZGF0YXNldDpfXwogIC0gRWFjaCByb3cgaW4gdGhpcyBkYXRhc2V0IGlzIGFuIGluc3BlY3Rpb24sIGFuZCBpZiBhbiBpbnNwZWN0aW9uIGF0IGEgcGFydGljdWxhciByZXN0YXVyYW50IHJlc3VsdHMgaW4gbXVsdGlwbGUgdmlvbGF0aW9ucywgdGhlcmUgd2lsbCBiZSBtdWx0aXBsZSByb3dzIGZvciB0aGF0IHJlc3RhdXJhbnQgd2l0aCB0aGUgc2FtZSBpbnNwZWN0aW9uIHNlcmlhbCBudW1iZXIKICAtIERhdGEgaXMgY29sbGVjdGVkIGZyb20gSmFudWFyeSAxc3QgMjAwNiB1bnRpbCBOb3ZlbWJlciAxM3RoIDIwMTkKICAKKyBfX0ZpcnN0IG9ic2VydmF0aW9uczpfXwogIC0gVGhlIGRhdGEgaXMgaW4gYSB0aWR5IGZvcm1hdAogIC0gVGhlcmUgYXJlIGByIG5yb3coaW5zcGVjdGlvbl9kYXRhKWAgb2JzZXJ2YXRpb25zIGFuZCBgciBuY29sKGluc3BlY3Rpb25fZGF0YSlgIHZhcmlhYmxlcyBpbiB0aGUgZGF0YSBzZXQKICAKKyBfX1ZhcmlhYmxlcyBleHBsYW5hdGlvbjpfXwogIC0gTmFtZTogT2ZmaWNpYWwgbmFtZSBvZiB0aGUgcmVzdGF1cmFudCBiZWluZyBpbnNwZWN0ZWQgKE5lZWQgdG8gYmUgYSBmYWN0b3IpICAKICAtIFByb2dyYW0gSWRlbnRpZmllcjogTmFtZSBvZiB0aGUgcmVzdGF1cmFudCBiZWluZyBpbnNwZWN0ZWQgKE5lZWQgdG8gYmUgYSBmYWN0b3IpICAKICAtIEluc3BlY3Rpb24gRGF0ZTogRGF0ZSBvZiB0aGUgZm9vZCBpbnNwZWN0aW9uIChOZWVkIHRvIGJlIGRhdGUgZm9ybWF0KSAgCiAgLSBEZXNjcmlwdGlvbjogQmFzZWQgb24gdGhlIHNlYXRpbmcgbnVtYmVyIGFuZCByaXNrIGNhdGVnb3JpZXM6IChOZWVkIHRvIGJlIGEgZmFjdG9yKSAgICAKICAgICAgICAgICAgICAgIC0gUmlzayBDYXRlZ29yeSBJOiBUaGV5IGRvIG5vdCBwcmVwYXJlIGZvb2Qgb24gc2l0ZSAgICAKICAgICAgICAgICAgICAgIC0gUmlzayBDYXRlZ29yeSBJSTogVGhleSBhc3NlbWJsZSBmb29kIG9uIHNpdGUsIGRvIG5vdCBwcmVwYXJlIGZyb20gc2NyYXRjaCAgICAKICAgICAgICAgICAgICAgIC0gUmlzayBDYXRlZ29yeSBJSUk6IFRoZXkgcHJlcGFyZSBmb29kIGZyb20gc2NyYXRjaCBhbmQgYXJlIG1vcmUgY29tcGxleCAgCiAgLSBBZGRyZXNzOiBBZGRyZXNzIG9mIHRoZSByZXN0YXVyYW50IGJlaW5nIGluc3BlY3RlZCAoTmVlZCB0byBiZSBhIGZhY3RvcikgIAogIC0gQ2l0eTogQ2l0eSBpbiB3aGljaCByZXN0YXVyYW50IGJlaW5nIGluc3BlY3RlZCBpcyBsb2NhdGVkIChOZWVkIHRvIGJlIGEgZmFjdG9yKSAgCiAgLSBaaXBjb2RlOiBaaXBjb2RlIHdoZXJlIHJlc3RhdXJhbnQgYmVpbmcgaW5zcGVjdGVkIGlzIGxvY2F0ZWQgKE5lZWQgdG8gYmUgYSBmYWN0b3IpICAKICAtIFBob25lOiBQaG9uZSBudW1iZXIgb2YgdGhlIHJlc3RhdXJhbnQgYmVpbmcgaW5zcGVjdGVkIChOZWVkIHRvIGJlIGEgZmFjdG9yKSAgCiAgLSBMb25naXR1ZGU6IExvbmdpdHVkaW5hbCBjb29yZGluYXRlcyBvZiB0aGUgcmVzdGF1cmFudCBzaXRlICAKICAtIExhdGl0dWRlOiBMYXRpdHVkaW5hbCBjb29yZGluYXRlcyBvZiB0aGUgcmVzdGF1cmFudCBzaXRlICAKICAtIEluc3BlY3Rpb24gQnVzaW5lc3MgTmFtZTogU2FtZSBhcyBvZmZpY2lhbCByZXN0YXVyYW50IG5hbWUgYmVpbmcgaW5zcGVjdGVkIChOZWVkIHRvIGJlIGEgZmFjdG9yKSAgCiAgLSBJbnNwZWN0aW9uIFR5cGU6IChOZWVkIHRvIGJlIGEgZmFjdG9yKSAgCiAgICAgICAgICAgICAgICAtIFJvdXRpbmUgSW5zcGVjdGlvbi9GaWVsZCBSZXZpZXc6IFNjb3JlZCBhbmQgdW5hbm5vdW5jZWQgaW5zcGVjdGlvbnMgIAogICAgICAgICAgICAgICAgLSBSZXR1cm4gSW5zcGVjdGlvbjogT2NjdXIgYXMgbmVlZGVkIHRvIGFkZHJlc3MgdmlvbGF0aW9ucyBvYnNlcnZlZCBkdXJpbmcgcm91dGluZSAgICAgCiAgICAgICAgICAgICAgICAgIG9ic2VydmF0aW9ucyAgCiAgICAgICAgICAgICAgICAtIENvbnN1bHRhdGlvbi9FZHVjYXRpb246IE1hbnkgcmVzdGF1cmFudHMgcmVjZWl2ZSBhbiB1bnNjb3JlZCBjb25zdWx0YXRpb24vZWR1Y2F0aW9uYWwgdmlzaXRzICAgICAgICAgICAgICAgICAgICAgZWFjaCB5ZWFyICAKICAtIEluc3BlY3Rpb24gU2NvcmU6IEN1bXVsYXRpdmUgZm9yIGFsbCB2aW9sYXRpb24gcG9pbnRzIGZvciBlYWNoIGluc3BlY3Rpb24gc2VyaWFsIG51bWJlcihNYXggNDAwKS4gSGlnaGVyIHRoZSBzY29yZSwgbW9yZSB0aGUgdmlvbGF0aW9ucyBvY2N1cmVkLlNjb3JlcyBvdmVyIDM1IG1heSByZXN1bHQgaW4gYSByZXR1cm4gaW5zcGVjdGlvbiAoTmVlZCB0byBiZSBhIE51bWVyaWMpICAgCiAgLSBJbnNwZWN0aW9uIFJlc3VsdDogKE5lZWQgdG8gYmUgYSBmYWN0b3IpICAgIAogICAgICAgICAgICAgICAgLSBNdWx0aXBsZSBjYXRlZ29yaWVzIGxpa2Ugc2F0aXNmYWN0b3J5LCB1bnNhdGlzZmFjdG9yeSwgY29tcGxldGUsIGluY29tcGxldGUgIAogIC0gSW5zcGVjdGlvbiBDbG9zZWQgQnVzaW5lc3M6IChOZWVkIHRvIGJlIGEgZmFjdG9yKSAgCiAgICAgICAgICAgICAgICAtIFRSVUU6IElmIHRoZSByZXN0YXVyYW50IHdhcyBjbG9zZWQgZHVlIHRvIG5vdCBtZWV0aW5nIG1pbmltdW0gc3RhbmRhcmRzICAKICAgICAgICAgICAgICAgIC0gRkFMU0U6IElmIHRoZSByZXN0YXVyYW50IG1ldCBtaW5pbXVtIHN0YW5kYXJkcyAgCiAgLSBWaW9sYXRpb24gVHlwZTogKE5lZWQgdG8gYmUgYSBmYWN0b3IpICAKICAgICAgICAgICAgICAgIC0gQkxVRTogTm90IG11Y2ggY3JpdGljYWwgdmlvbGF0aW9ucyBsaWtlIG1haW50YWluYW5jZSBhbmQgc2FuaXRhdGlvbiBpc3N1ZXMgd2l0aCB0aGUgcmVzdGF1cmFudCAgCiAgICAgICAgICAgICAgICAtIFJFRDogQ3JpdGljYWwgdmlvbGF0aW9ucyBsZWFkaW5nIHRvIGZvb2QtYm9ybmUgZGlzZWFzZXMgIAogIC0gVmlvbGF0aW9uIERlc2NyaXB0aW9uOiBEaWZmZXJlbnQgdHlwZXMgb2YgdmlvbGF0aW9ucyBsaWtlOiAoTmVlZCB0byBiZSBhIGZhY3RvcikgIAogICAgICAgICAgICAgICAgLSA0MTAwOiBXYXJld2FzaGluZyBmYWNpbGl0aWVzIHByb3Blcmx5IGluc3RhbGxlZCAgCiAgICAgICAgICAgICAgICAtIDM0MDA6IFdpcGluZyBjbG90aHMgcHJvcGVybHkgdXNlZCwgc3RvcmVkLCBwcm9wZXIgc2FuaXRpemVyLCBhbmQgbW9yZSAgCiAgLSBWaW9sYXRpb24gUG9pbnRzOiBTY29yZSBmb3IgZWFjaCB2aW9sYXRpb24gKE5lZWQgdG8gYmUgYSBudW1lcmljKSAgCiAgLSBCdXNpbmVzc19JRDogSWRlbnRpZmllciBvZiB0aGUgcmVzdGF1cmFudCAoTmVlZCB0byBiZSBhIGZhY3RvcikgIAogIC0gSW5zcGVjdGlvbl9TZXJpYWxfTnVtOiBVbmlxdWUgbnVtYmVyIGZvciBlYWNoIGluc3BlY3Rpb24uIFRoZXkgY2FuIGJlIG11bHRpcGxlIGlmIHRoZXJlIGFyZSBtb3JlIHRoYW4gMSB2aW9sYXRpb25zIGluIG9uZSBpbnNwZWN0aW9uLiAgKE5lZWQgdG8gYmUgYSBmYWN0b3IpICAKICAtIFZpb2xhdGlvbl9SZWNvcmRfSUQ6IElkZW50aWZpZXIgZm9yIGVhY2ggdmlvbGF0aW9uIHJlY29yZCAoTmVlZCB0byBiZSBhIGZhY3RvcikgIAogIC0gR3JhZGU6IFRoZXNlIGdyYWRlcyBhcmUgY2FsY3VsYXRlZCBiYXNlZCBvbiBaaXBjb2RlczogKE5lZWQgdG8gYmUgYSBmYWN0b3IpICAKICAgICAgICAgICAgICAgIC0gMTogRXhjZWxsZW50IChXaGVuIE5vL2ZldyByZWQgY3JpdGljYWwgdmlvbGF0aW9ucyBoYXZlIG9jY3VycmVkKSAgICAKICAgICAgICAgICAgICAgIC0gMjogR29vZCAoIFdoZW4gc29tZSByZWQgY3JpdGljYWwgdmlvbGF0aW9ucyBoYXZlIG9jY3VycmVkKSAgCiAgICAgICAgICAgICAgICAtIDM6IE9rYXkgKFdoZW4gbWFueSByZWQgY3JpdGljYWwgdmlvbGF0aW9ucyBoYXZlIG9jY3VycmVkKSAgCiAgICAgICAgICAgICAgICAtIDQ6IE5lZWRzIHRvIGltcHJvdmUgKEVpdGhlciB0aGUgcmVzdGF1cmFudCBjbG9zZWQgd2l0aGluIGxhc3QgeWVhciBvciByZXN0YXVyYW50IG5lZWRlZCBtdWx0aXBsZSAgICAgICAgICAgICAgICAgICAgICBpbnNwZWN0aW9ucyB0byBmaXggc2FmZXR5IHByYWN0aWNlcywgdGhpcyBpcyBub3QgYWRqdXN0ZWQgYnkgemlwY29kZSkgIAoKIyBBZGp1c3RpbmcgZGF0YQpgYGB7ciBhZGp1c3RpbmcsIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMgU2VwYXJ0aW5nIGNvbHVtbnMgRGVzY3JpcHRpb24gIGFuZCBWaW9sYXRpb24gRGVzY3JpcHRpb24gaW50byB0d28gY29sdW1ucyBlYWNoCmluc3BlY3Rpb25fZGF0YSRTZWF0aW5nIDwtIGFzLmZhY3RvcigoaW5zcGVjdGlvbl9kYXRhICU+JXNlcGFyYXRlKERlc2NyaXB0aW9uLCBjKCdTZWF0aW5nJywnUmlzayBDYXRlZ29yeScpLCBzZXAgPSAiIC0gUmlzayAiKSkkU2VhdGluZykgIAoKaW5zcGVjdGlvbl9kYXRhJFJpc2tfQ2F0ZWdvcnkgPC0gYXMuZmFjdG9yKChpbnNwZWN0aW9uX2RhdGEgJT4lc2VwYXJhdGUoRGVzY3JpcHRpb24sIGMoJ1NlYXRpbmcnLCdSaXNrIENhdGVnb3J5JyksIHNlcCA9ICIgLSAiKSkkYFJpc2sgQ2F0ZWdvcnlgKSAgCgppbnNwZWN0aW9uX2RhdGEkVmlvbGF0aW9uX051bWJlciA8LSBhcy5mYWN0b3IoKGluc3BlY3Rpb25fZGF0YSAlPiUgc2VwYXJhdGUoYFZpb2xhdGlvbiBEZXNjcmlwdGlvbmAsIGMoJ1Zpb2xhdGlvbiBOdW1iZXInLCdWaW9sYXRpb24gRGVzY3JpcHRpb24nKSwgc2VwID0gIiAtICIpKSRgVmlvbGF0aW9uIE51bWJlcmApICAKCmluc3BlY3Rpb25fZGF0YSRWaW9sYXRpb25fRGVzY3JpcHRpb24gPC0gYXMuZmFjdG9yKChpbnNwZWN0aW9uX2RhdGEgJT4lIHNlcGFyYXRlKGBWaW9sYXRpb24gRGVzY3JpcHRpb25gLCBjKCdWaW9sYXRpb24gTnVtYmVyJywnVmlvbGF0aW9uIERlc2NyaXB0aW9uJyksIHNlcCA9ICIgLSAiKSkkYFZpb2xhdGlvbiBEZXNjcmlwdGlvbmApICAKCiMgUmVzdHJ1Y3R1cmluZyByaXNrIGNhdGVnb3JpZXMKaW5zcGVjdGlvbl9kYXRhICU8PiUgbXV0YXRlKFJpc2tfQ2F0ZWdvcnkgPSBjYXNlX3doZW4oCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBSaXNrX0NhdGVnb3J5ID09ICJSaXNrIENhdGVnb3J5IEkiIH4gIlJpc2sgQ2F0ZWdvcnkgSSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBSaXNrX0NhdGVnb3J5ID09ICJSaXNrIElJIiB+ICJSaXNrIENhdGVnb3J5IElJIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJpc2tfQ2F0ZWdvcnkgPT0gIlJpc2sgQ2F0ZWdvcnkgSUkiIH4gIlJpc2sgQ2F0ZWdvcnkgSUkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUmlza19DYXRlZ29yeSA9PSAiUmlzayBJSSZJSUkiIH4gIlJpc2sgQ2F0ZWdvcnkgSUkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUmlza19DYXRlZ29yeSA9PSAiUmlzayBDYXRlZ29yeSBJSUkiIH4gIlJpc2sgQ2F0ZWdvcnkgSUlJIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJpc2tfQ2F0ZWdvcnkgPT0gIm5vIHBlcm1hbmVudCBwbHVtYmluZyIgfiAiUmlzayBDYXRlZ29yeSBJIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgIAoKIyBBZGp1c3RpbmcgZGF0YSB0eXBlcyBhbmQgbmFtZXMgb2YgdGhlIHZhcmlhYmxlcwppbnNwZWN0aW9uX2RhdGEgPC0gaW5zcGVjdGlvbl9kYXRhICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShOYW1lID0gIGFzLmZhY3RvcihOYW1lKSwgI05BID0gMAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUHJvZ3JhbV9JZGVudGlmaWVyID0gYXMuZmFjdG9yKGBQcm9ncmFtIElkZW50aWZpZXJgKSwgI05BID0gMSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEluc3BlY3Rpb25fRGF0ZSA9ICBhcy5EYXRlKGBJbnNwZWN0aW9uIERhdGVgLCAiJW0vJWQvJVkiKSwgI05BID0gNTMwCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBBZGRyZXNzID0gIGFzLmZhY3RvcihBZGRyZXNzKSwgI05BID0gMAogICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2l0eSA9ICBhcy5mYWN0b3IodG91cHBlcihDaXR5KSksICNOQSA9IDAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFppcENvZGUgPSAgYXMuZmFjdG9yKGBaaXAgQ29kZWApLCAjTkEgPSAxCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBQaG9uZSA9ICBhcy5mYWN0b3IoUGhvbmUpLCAjTkEgPSA4MjA2NAogICAgICAgICAgICAgICAgICAgICAgICAgICAgSW5zcGVjdGlvbl9CdXNpbmVzc19OYW1lID0gIGFzLmZhY3RvcihgSW5zcGVjdGlvbiBCdXNpbmVzcyBOYW1lYCksICNOQSA9IDUzMAogICAgICAgICAgICAgICAgICAgICAgICAgICAgSW5zcGVjdGlvbl9UeXBlID0gIGFzLmZhY3RvcihgSW5zcGVjdGlvbiBUeXBlYCksICNOQSA9IDUzMAogICAgICAgICAgICAgICAgICAgICAgICAgICAgSW5zcGVjdGlvbl9TY29yZSA9ICBhcy5udW1lcmljKGBJbnNwZWN0aW9uIFNjb3JlYCksICNOQSA9IDU4NAogICAgICAgICAgICAgICAgICAgICAgICAgICAgSW5zcGVjdGlvbl9SZXN1bHQgPSAgYXMuZmFjdG9yKGBJbnNwZWN0aW9uIFJlc3VsdGApLCNOQSA9IDUzMAogICAgICAgICAgICAgICAgICAgICAgICAgICAgSW5zcGVjdGlvbl9DbG9zZWRfQnVzaW5lc3MgPSAgYXMuZmFjdG9yKGBJbnNwZWN0aW9uIENsb3NlZCBCdXNpbmVzc2ApLCAjTkEgPSA1MzAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZpb2xhdGlvbl9UeXBlID0gIGFzLmZhY3RvcihgVmlvbGF0aW9uIFR5cGVgKSwgI05BID0gMTE4OTE3CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBWaW9sYXRpb25fUG9pbnRzID0gIGFzLm51bWVyaWMoYFZpb2xhdGlvbiBQb2ludHNgKSwgI05BID0gMAogICAgICAgICAgICAgICAgICAgICAgICAgICAgQnVzaW5lc3NfSUQgPSAgYXMuZmFjdG9yKEJ1c2luZXNzX0lEKSwgI05BID0gMAogICAgICAgICAgICAgICAgICAgICAgICAgICAgSW5zcGVjdGlvbl9TZXJpYWxfTnVtID0gIGFzLmZhY3RvcihJbnNwZWN0aW9uX1NlcmlhbF9OdW0pLCAjTkEgPSA1MzAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZpb2xhdGlvbl9SZWNvcmRfSUQgPSAgYXMuZmFjdG9yKFZpb2xhdGlvbl9SZWNvcmRfSUQpLCAjTkEgPSAxMTg5MTcKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEdyYWRlID0gIGFzLmZhY3RvcihHcmFkZSksICNOQSA9IDU5MzYyCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBSaXNrX0NhdGVnb3J5ID0gYXMuZmFjdG9yKFJpc2tfQ2F0ZWdvcnkpICNOQSA9IDAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKCgojVmFyaWFibGVzIC0gTmFtZSwgUHJvZ3JhbSBJbmRlbnRpZmllciBhbmQgSW5zcGVjdGlvbiBCdXNpbmVzcyBOYW1lIHNoYXJlIHRoZSBzYW1lIGRhdGEsIHNvIHdlIGFyZSBnb2luZyB0byBrZWVwIG9ubHkgdGhlIHByb2dyYW0gaWRlbnRpZmllciBhbmQgcmVtb3ZlIHRoZSBvdGhlciB0d28sIGFsb3MgZW1wdHlpbmcgdGhlIHByZXZpb3VzIGNvbHVtbiBuYW1lcwppbnNwZWN0aW9uX2RhdGEkTmFtZSA8LSBOVUxMCmluc3BlY3Rpb25fZGF0YSRgUHJvZ3JhbSBJZGVudGlmaWVyYCA8LSBOVUxMCmluc3BlY3Rpb25fZGF0YSRgSW5zcGVjdGlvbiBEYXRlYCA8LSBOVUxMCmluc3BlY3Rpb25fZGF0YSRgWmlwIENvZGVgIDwtIE5VTEwKaW5zcGVjdGlvbl9kYXRhJGBJbnNwZWN0aW9uIEJ1c2luZXNzIE5hbWVgIDwtIE5VTEwKaW5zcGVjdGlvbl9kYXRhJEluc3BlY3Rpb25fQnVzaW5lc3NfTmFtZSA8LSBOVUxMCmluc3BlY3Rpb25fZGF0YSRgSW5zcGVjdGlvbiBUeXBlYCA8LSBOVUxMCmluc3BlY3Rpb25fZGF0YSRgSW5zcGVjdGlvbiBSZXN1bHRgIDwtIE5VTEwKaW5zcGVjdGlvbl9kYXRhJGBJbnNwZWN0aW9uIFNjb3JlYCA8LSBOVUxMCmluc3BlY3Rpb25fZGF0YSRgSW5zcGVjdGlvbiBDbG9zZWQgQnVzaW5lc3NgIDwtIE5VTEwKaW5zcGVjdGlvbl9kYXRhJGBWaW9sYXRpb24gVHlwZWAgPC0gTlVMTAppbnNwZWN0aW9uX2RhdGEkYFZpb2xhdGlvbiBQb2ludHNgIDwtIE5VTEwKaW5zcGVjdGlvbl9kYXRhJERlc2NyaXB0aW9uIDwtIE5VTEwgICAKaW5zcGVjdGlvbl9kYXRhJGBWaW9sYXRpb24gRGVzY3JpcHRpb25gIDwtIE5VTEwgIAoKI0xvb2tpbmcgZm9yIDUzMCByb3dzIHdoZXJlIGluc3BlY3Rpb24gc2VyaWFsIG51bWJlciBpcyBOQSBhbmQgd2lsbCBkcm9wIHRob3NlIHJvd3MKaW5zcGVjdGlvbl9kYXRhIDwtIGluc3BlY3Rpb25fZGF0YSAlPiUgZHJvcF9uYShJbnNwZWN0aW9uX1NlcmlhbF9OdW0pCgojRHJvcHBpbmcgMSByb3cgd2hlcmUgUHJvZ3JhbSBJZGVudGlmaWVyIGlzIE5BCmluc3BlY3Rpb25fZGF0YSA8LSBpbnNwZWN0aW9uX2RhdGEgJT4lIGRyb3BfbmEoUHJvZ3JhbV9JZGVudGlmaWVyKQoKI0Ryb3BwaW5nIDEgcm93IHdoZXJlIFppcGNvZGUgaXMgTkEKaW5zcGVjdGlvbl9kYXRhIDwtIGluc3BlY3Rpb25fZGF0YSAlPiUgZHJvcF9uYShaaXBDb2RlKQoKI0NyZWF0ZSBmYWN0b3JzIGZvciBOQSB2YWx1ZXMgCgojRmFjdG9yIGxldmVsICdNaXNzaW5nJyBmb3IgcmVtYWluaW5nIDgyMDMxIE5BIHBob25lIHZhbHVlcyBhbmQgNTg5MDIgTkEgZ3JhZGUgdmFsdWVzCmluc3BlY3Rpb25fZGF0YSRQaG9uZSA8LSBmY3RfZXhwbGljaXRfbmEoaW5zcGVjdGlvbl9kYXRhJFBob25lKQppbnNwZWN0aW9uX2RhdGEkR3JhZGUgPC0gZmN0X2V4cGxpY2l0X25hKGluc3BlY3Rpb25fZGF0YSRHcmFkZSkKCiNGYWN0b3IgbGV2ZWwgJ05PTkUnIGZvciB2aW9sYXRpb24gbnVtYmVycywgdmlvbGF0aW9uIGRlc2NyaXB0aW9ucywgdmlvbGF0aW9uIHR5cGVzLHZpb2xhdGlvbiByZWNvcmQgSURzIChOQSA9IDExODM4NikKaW5zcGVjdGlvbl9kYXRhJFZpb2xhdGlvbl9UeXBlIDwtIGZjdF9leHBsaWNpdF9uYShpbnNwZWN0aW9uX2RhdGEkVmlvbGF0aW9uX1R5cGUsIG5hX2xldmVsID0gIk5PTkUiKQppbnNwZWN0aW9uX2RhdGEkVmlvbGF0aW9uX1JlY29yZF9JRCA8LSBmY3RfZXhwbGljaXRfbmEoaW5zcGVjdGlvbl9kYXRhJFZpb2xhdGlvbl9SZWNvcmRfSUQsIG5hX2xldmVsID0gIk5PTkUiKQppbnNwZWN0aW9uX2RhdGEkVmlvbGF0aW9uX051bWJlciA8LSBmY3RfZXhwbGljaXRfbmEoaW5zcGVjdGlvbl9kYXRhJFZpb2xhdGlvbl9OdW1iZXIsIG5hX2xldmVsID0gIk5PTkUiKQppbnNwZWN0aW9uX2RhdGEkVmlvbGF0aW9uX0Rlc2NyaXB0aW9uIDwtIGZjdF9leHBsaWNpdF9uYShpbnNwZWN0aW9uX2RhdGEkVmlvbGF0aW9uX0Rlc2NyaXB0aW9uLCBuYV9sZXZlbCA9ICJOT05FIikKCiNXZSBzdGlsbCBoYXZlIDU0IHJvd3Mgd2hlcmUgaW5zcGVjdGlvbiBzY29yZXMgYXJlIE5BLCBjcmVhdGluZyBhIG5ldyB0YWJsZSBmb3IgdGhlbQpuYV9zY29yZSA8LSBpbnNwZWN0aW9uX2RhdGFbaXMubmEoaW5zcGVjdGlvbl9kYXRhJEluc3BlY3Rpb25fU2NvcmUpLF0gJT4lIHNlbGVjdCg3LDE4KQojRHJvcCByb3dzIHdpdGggZHVwbGljYXRlIGluc3BlY3Rpb24gc2VyaWFsIG51bWJlcgpuYV9zY29yZSA8LSBuYV9zY29yZVshZHVwbGljYXRlZChuYV9zY29yZSRJbnNwZWN0aW9uX1NlcmlhbF9OdW0pLF0KCiNMb29raW5nIGZvciB0aG9zZSBpbnNwZWN0aW9uIHNlcmlhbCBudW1iZXJzIHdpdGggTkEgaW5zcGVjdGlvbiBzY29yZSBpbiB0aGUgb3JpZ2luYWwgdGFibGUgYW5kIHN1bW1pbmcgdGhlaXIgdmlvbGF0aW9uIHBvaW50cyB0byBmaW5kIG91dCBpbnNwZWN0aW9uIHNjb3JlCmZvciAocm93IGluIDE6bnJvdyhuYV9zY29yZSkpIHsKICBkZiA8LSBpbnNwZWN0aW9uX2RhdGFbaW5zcGVjdGlvbl9kYXRhJEluc3BlY3Rpb25fU2VyaWFsX051bSA9PSBuYV9zY29yZVtyb3csICJJbnNwZWN0aW9uX1NlcmlhbF9OdW0iXSRJbnNwZWN0aW9uX1NlcmlhbF9OdW0sXQogIHNjb3JlIDwtIHN1bShkZiRWaW9sYXRpb25fUG9pbnRzKQogIG5hX3Njb3JlW3JvdywgIkluc3BlY3Rpb25fU2NvcmUiXSRJbnNwZWN0aW9uX1Njb3JlIDwtIHNjb3JlCn0KCiNNZXJnaW5nIGJvdGggdGhlIHRhYmxlcyBuYV9zY29yZSBhbmQgaW5zcGVjdGlvbl9kYXRhCmluc3BlY3Rpb25fZGF0YSA8LSBtZXJnZShpbnNwZWN0aW9uX2RhdGEsbmFfc2NvcmUsIGJ5ID0gYygnSW5zcGVjdGlvbl9TZXJpYWxfTnVtJyksIGFsbC54ID0gVFJVRSkKaW5zcGVjdGlvbl9kYXRhJEluc3BlY3Rpb25fU2NvcmUueFtpcy5uYShpbnNwZWN0aW9uX2RhdGEkSW5zcGVjdGlvbl9TY29yZS54KV0gPC0gaW5zcGVjdGlvbl9kYXRhJEluc3BlY3Rpb25fU2NvcmUueVtpcy5uYShpbnNwZWN0aW9uX2RhdGEkSW5zcGVjdGlvbl9TY29yZS54KV0KCm5hX3Njb3JlIDwtIE5VTEwKaW5zcGVjdGlvbl9kYXRhJEluc3BlY3Rpb25fU2NvcmUgPC0gaW5zcGVjdGlvbl9kYXRhJEluc3BlY3Rpb25fU2NvcmUueAppbnNwZWN0aW9uX2RhdGEkSW5zcGVjdGlvbl9TY29yZS54IDwtIE5VTEwKaW5zcGVjdGlvbl9kYXRhJEluc3BlY3Rpb25fU2NvcmUueSA8LSBOVUxMCgojIExvb2tpbmcgZm9yIHRob3NlIHJvd3Mgd2hlcmUgaW5zcGVjdGlvbiBzY29yZSA8IDAKbmVnYXRpdmVfdmFsdWVzIDwtIGluc3BlY3Rpb25fZGF0YSAlPiUgCiAgZmlsdGVyKEluc3BlY3Rpb25fU2NvcmUgPCAwKSAlPiUgCiAgc2VsZWN0KDEsMjIpCgpmb3IgKHJvdyBpbiAxOm5yb3cobmVnYXRpdmVfdmFsdWVzKSkgewogIGRmIDwtIGluc3BlY3Rpb25fZGF0YVtpbnNwZWN0aW9uX2RhdGEkSW5zcGVjdGlvbl9TZXJpYWxfTnVtID09IG5lZ2F0aXZlX3ZhbHVlc1tyb3csICJJbnNwZWN0aW9uX1NlcmlhbF9OdW0iXSxdCiAgc2NvcmUgPC0gc3VtKGRmJFZpb2xhdGlvbl9Qb2ludHMpCiAgbmVnYXRpdmVfdmFsdWVzW3JvdywgIkluc3BlY3Rpb25fU2NvcmUiXSA8LSBzY29yZQp9CgojTWVyZ2luZyBib3RoIHRoZSB0YWJsZXMgbmVnYXRpdmVfdmFsdWVzIGFuZCBpbnNwZWN0aW9uX2RhdGEKaW5zcGVjdGlvbl9kYXRhIDwtIG1lcmdlKGluc3BlY3Rpb25fZGF0YSxuZWdhdGl2ZV92YWx1ZXMsIGJ5ID0gYygnSW5zcGVjdGlvbl9TZXJpYWxfTnVtJyksIGFsbC54ID0gVFJVRSkKaW5zcGVjdGlvbl9kYXRhJEluc3BlY3Rpb25fU2NvcmUueFtpbnNwZWN0aW9uX2RhdGEkSW5zcGVjdGlvbl9TY29yZS54IDwgMF0gPC0gaW5zcGVjdGlvbl9kYXRhJEluc3BlY3Rpb25fU2NvcmUueVtpbnNwZWN0aW9uX2RhdGEkSW5zcGVjdGlvbl9TY29yZS54IDwgMF0KCm5lZ2F0aXZlX3ZhbHVlcyA8LSBOVUxMCmluc3BlY3Rpb25fZGF0YSRJbnNwZWN0aW9uX1Njb3JlIDwtIGluc3BlY3Rpb25fZGF0YSRJbnNwZWN0aW9uX1Njb3JlLngKaW5zcGVjdGlvbl9kYXRhJEluc3BlY3Rpb25fU2NvcmUueCA8LSBOVUxMCmluc3BlY3Rpb25fZGF0YSRJbnNwZWN0aW9uX1Njb3JlLnkgPC0gTlVMTAoKI1dvcmtpbmcgb24gaW5zcGVjdGlvbiBkYXRlCmluc3BlY3Rpb25fZGF0YSRZZWFyIDwtIGZvcm1hdChpbnNwZWN0aW9uX2RhdGEkSW5zcGVjdGlvbl9EYXRlLCIlWSIpCmluc3BlY3Rpb25fZGF0YSRNb250aCA8LSBmb3JtYXQoaW5zcGVjdGlvbl9kYXRhJEluc3BlY3Rpb25fRGF0ZSwiJW0iKQoKaW5zcGVjdGlvbl9kYXRhICU8PiUgbXV0YXRlKFllYXIgPSBjYXNlX3doZW4oCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBZZWFyID09ICIwMDA2IiB+ICIyMDA2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFllYXIgPT0gIjAwMDciIH4gIjIwMDciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgWWVhciA9PSAiMDAwOCIgfiAiMjAwOCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBZZWFyID09ICIwMDA5IiB+ICIyMDA5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFllYXIgPT0gIjAwMTAiIH4gIjIwMTAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgWWVhciA9PSAiMDAxMSIgfiAiMjAxMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBZZWFyID09ICIwMDEyIiB+ICIyMDEyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFllYXIgPT0gIjAwMTMiIH4gIjIwMTMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgWWVhciA9PSAiMDAxNCIgfiAiMjAxNCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBZZWFyID09ICIwMDE1IiB+ICIyMDE1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFllYXIgPT0gIjAwMTYiIH4gIjIwMTYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgWWVhciA9PSAiMDAxNyIgfiAiMjAxNyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBZZWFyID09ICIwMDE4IiB+ICIyMDE4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFllYXIgPT0gIjAwMTkiIH4gIjIwMTkiKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQoKaW5zcGVjdGlvbl9kYXRhJEluc3BlY3Rpb25fRGF0ZSA8LSBOVUxMCgojUmVhcnJhbmdpbmcgdGhlIGNvbHVtbnMKaW5zcGVjdGlvbl9kYXRhIDwtIGluc3BlY3Rpb25fZGF0YVssYygxNCw3LDIsNCwzLDE1LDUsNiwyMiwyMywxNiwyMSwxNywxOCwxLDE5LDEyLDEzLDgsMjAsMTAsMTEsOSldCnN0cihpbnNwZWN0aW9uX2RhdGEpCmBgYAoKKyBfX0Fib3V0IHRoZSBkYXRhc2V0Ol9fCiAgLSBBZnRlciBjbGVhbmluZywgd2Ugbm93IGhhdmUgYHIgaW5zcGVjdGlvbl9kYXRhICU+JSBucm93YCBvYnNlcnZhdGlvbnMgYW5kIGByIGluc3BlY3Rpb25fZGF0YSAlPiUgbmNvbGAgdmFyaWFibGVzIAogCiMgQmFzZSBFREEgCgojIyBVbmktdmFyaWF0ZSBub24tZ3JhcGhpY2FsIEVEQSAKCiMjIyBWYXJpYWJsZXMgd2hpY2ggZG8gbm90IG5lZWQgZm9yIHVzIHRvIHJlbW92ZSBkdXBsaWNhdGVzIGJhc2VkIG9uIGluc3BlY3Rpb24gc2VyaWFsIG51bWJlciAKYGBge3Igc3VtbWFyeSwgd2FybmluZyA9IEZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQppbnNwZWN0aW9uX2RhdGEgICU+JSBzZWxlY3QoVmlvbGF0aW9uX1R5cGUsIFZpb2xhdGlvbl9OdW1iZXIsIFZpb2xhdGlvbl9EZXNjcmlwdGlvbiwgVmlvbGF0aW9uX1JlY29yZF9JRCwgVmlvbGF0aW9uX1BvaW50cykgJT4lIHN1bW1hcnkoKSAKYGBgCgorIF9fRmluZGluZ3M6X18KICAtIEJMVUUgdmlvbGF0aW9ucyBoYXZlIG9jY3VycmVkIGByIHJvdW5kKChpbnNwZWN0aW9uX2RhdGEgJT4lIGZpbHRlcihWaW9sYXRpb25fVHlwZSA9PSAnQkxVRScpICU+JSBucm93KCkpLyhpbnNwZWN0aW9uX2RhdGEgJT4lIG5yb3coKSkqMTAwLDIpYCUgb2YgdGltZXMuIFJFRCB2aW9sYXRpb25zIGhhdmUgb2NjdXJlZCBgciByb3VuZCgoaW5zcGVjdGlvbl9kYXRhICU+JSBmaWx0ZXIoVmlvbGF0aW9uX1R5cGUgPT0gJ1JFRCcpICU+JSBucm93KCkpLyhpbnNwZWN0aW9uX2RhdGEgJT4lIG5yb3coKSkqMTAwLDIpYCUgb2YgdGltZXMuIE5vIHZpb2xhdGlvbnMgb2NjdXJyZWQgYHIgcm91bmQoKGluc3BlY3Rpb25fZGF0YSAlPiUgZmlsdGVyKFZpb2xhdGlvbl9UeXBlID09ICdOT05FJykgJT4lIG5yb3coKSkvKGluc3BlY3Rpb25fZGF0YSAlPiUgbnJvdygpKSoxMDAsMilgJSBvZiB0aW1lcy4gIAogIC0gVGhlcmUgYXJlIHZhcmlvdXMgdHlwZXMgb2YgdmlvbGF0aW9ucyBvY2N1cnJpbmcgY2F0ZWdvcml6ZWQgYnkgVmlvbGF0aW9uX051bWJlciBhbmQgdGhlaXIgY29ycmVzcG9uZGluZyBkZWNyaXB0aW9ucyB1bmRlciBWaW9sYXRpb25fRGVzY3JpcHRpb24gIAogIC0gRm9yIHZpb2xhdGlvbiBwb2ludHMsIEkgYW0gZ29pbmcgdG8gY29uc2lkZXIgbWVkaWFuIGByIG1lZGlhbihpbnNwZWN0aW9uX2RhdGEkVmlvbGF0aW9uX1BvaW50cylgIGFzIHRoZSBtZWFzdXJlIG9mIGNlbnRyYWwgdGVuZGVuY3kgc2luY2UgdGhlIGRpc3RyaWJ1dGlvbiBpcyBza2V3ZWQgIAoKIyMjIFZhcmlhYmxlcyB3aGljaCBuZWVkIGZvciB1cyB0byByZW1vdmUgZHVwbGljYXRlcyBiYXNlZCBvbiBpbnNwZWN0aW9uIHNlcmlhbCBudW1iZXIgCmBgYHtyfQppbnNwZWN0aW9uX2RhdGFfbm90X2R1cCA8LSBpbnNwZWN0aW9uX2RhdGFbIWR1cGxpY2F0ZWQoaW5zcGVjdGlvbl9kYXRhJEluc3BlY3Rpb25fU2VyaWFsX051bSksXQoKaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lIHNlbGVjdCgtVmlvbGF0aW9uX1R5cGUsIC1WaW9sYXRpb25fTnVtYmVyLCAtVmlvbGF0aW9uX0Rlc2NyaXB0aW9uLCAtVmlvbGF0aW9uX1JlY29yZF9JRCwgLVZpb2xhdGlvbl9Qb2ludHMpICU+JSBzdW1tYXJ5KCkKYGBgCgorIF9fRmluZGluZ3M6X18KICAtIFRoZXJlIGFyZSBgciBsZW5ndGgodW5pcXVlKGluc3BlY3Rpb25fZGF0YSRQcm9ncmFtX0lkZW50aWZpZXIpKWAgdW5pcXVlIHJlc3RhdXJhbnRzIGJlaW5nIGluc3BlY3RlZCBieSBLaW5nIENvdW50eSBmb3IgZm9vZCBzYWZldHkgICAgCiAgLSBUaGVyZSBhcmUgYHIgbGVuZ3RoKHVuaXF1ZShpbnNwZWN0aW9uX2RhdGEkQ2l0eSkpYCBjaXRpZXMgY292ZXJlZCBieSBLaW5nIENvdW50eSBmb3IgRm9vZCAgICAgICAgICAgICAgICAgICAgIEluc3BlY3Rpb25zLiBGZXcgb2Ygd2hpY2ggYXJlIFNlYXR0bGUsIEJlbGxldnVlLCBLZW50LCBSZW50b24sIEZlZGVyYWwgV2F5LCBSZWRtb25kIGFuZCBtYW55IG1vcmUgIAogIC0gQWxtb3N0IGhhbGYgb2YgdGhlIGluc3BlY3Rpb25zIGByIHJvdW5kKChpbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUgZmlsdGVyKENpdHkgPT0gJ1NFQVRUTEUnKSAlPiUgbnJvdygpKS8oaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lIG5yb3coKSkqMTAwLDIpYCUgYXJlIGNhcnJpZWQgb3V0IGluIFNlYXR0bGUgICAKICAtIEluc3BlY3Rpb25zIGFyZSBjYXJyaWVkIG91dCBhY3Jvc3MgYHIgbGVuZ3RoKHVuaXF1ZShpbnNwZWN0aW9uX2RhdGEkWmlwQ29kZSkpYCBaaXBjb2RlcyBpbiBLaW5nIENvdW50eSAgCiAgLSBXZSBhbHNvIGhhdmUgY29vcmRpbmF0ZXMgYXZhaWxhYmxlIGZvciBhbGwgdGhlIHJlc3RhdXJhbnRzIGJlaW5nIGluc3BlY3RlZCAgCiAgLSBUaGUgZGF0YSBpcyBiZWdpbm5pbmcgZnJvbSBKYW51YXJ5IDIwMDYgdW50aWwgbWlkIE5vdmVtYmVyIDIwMTkgIAogIC0gYHIgcm91bmQoKGluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JSBmaWx0ZXIoSW5zcGVjdGlvbl9UeXBlID09ICJSb3V0aW5lIEluc3BlY3Rpb24vRmllbGQgUmV2aWV3IikgJT4lIG5yb3coKSkvKGluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JSBucm93KCkpKjEwMCwyKWAlIG9mIGluc3BlY3Rpb25zIGNhcnJpZWQgb3V0IGJ5IEtpbmcgQ291bnR5IGFyZSBSb3V0aW5lL0ZpZWxkIFJldmlld3MgIAogIC0gTWVhbiBhbmQgbWVkaWFuIG9mIGluc3BlY3Rpb24gc2NvcmUgYXJlIGRpZmZlcmVudCwgd2hpY2ggbWVhbnMgdGhlIGRhdGEgaXMgc2tld2VkIHNvIHdlIHdpbGwgYmUgdXNpbmcgbWVkaWFuIGFzIHRoZSBtZWFzdXJlIG9mIGNlbnRyYWwgdGVuZGVuY3kgIAogIC0gVGhlIGluc3BlY3Rpb24gaGFzIGJlZW4gc2F0aXNmYWN0b3J5IGByIHJvdW5kKChpbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUgZmlsdGVyKEluc3BlY3Rpb25fUmVzdWx0ID09ICJTYXRpc2ZhY3RvcnkiKSAlPiUgbnJvdygpKS8oaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lIG5yb3coKSkqMTAwLDIpYCUgb2YgdGltZXMuIFRoZSBpbnNwZWN0aW9uIGhhcyBiZWVuIHVuc2F0aXNmYWN0b3J5IGByIHJvdW5kKChpbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUgZmlsdGVyKEluc3BlY3Rpb25fUmVzdWx0ID09ICJVbnNhdGlzZmFjdG9yeSIpICU+JSBucm93KCkpLyhpbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUgbnJvdygpKSoxMDAsMilgJSBvZiB0aW1lcy4gVGhlIGluc3BlY3Rpb24gaGFzIGJlZW4gY29tcGxldGUgYHIgcm91bmQoKGluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JSBmaWx0ZXIoSW5zcGVjdGlvbl9SZXN1bHQgPT0gIkNvbXBsZXRlIikgJT4lIG5yb3coKSkvKGluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JSBucm93KCkpKjEwMCwyKWAlIG9mIHRpbWVzLiAgIAogIC0gVGhlIHJlc3RhdXJhbnRzIGFyZSBjbG9zZWQgYHIgcm91bmQoKGluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JSBmaWx0ZXIoSW5zcGVjdGlvbl9DbG9zZWRfQnVzaW5lc3MgPT0gVFJVRSkgJT4lIG5yb3coKSkvKGluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JSBucm93KCkpKjEwMCwyKWAlIG9mIHRpbWVzLCB3aGljaCBtZWFucyB0aGV5IGRpZCBub3QgbWVldCBtaW5pbXVtIGhlYWx0aCBzdGFuZGFyZHMgZHVyaW5nIHRoZSBpbnNwZWN0aW9uLiBJdCBpcyBwb3NzaWJsZSB0aGF0IHRoZXkgY291bGQgaGF2ZSBiZWVuIHJlb3BlbmVkIGFnYWluLiAgCiAgLSBPdXQgb2YgdW5pcXVlIGByIGluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JSBucm93KClgIGluc3BlY3Rpb25zLCBgciByb3VuZCgoaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lIGZpbHRlcihTZWF0aW5nID09ICdTZWF0aW5nIDEzLTUwJykgJT4lIG5yb3coKSkvKGluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JSBucm93KCkpKjEwMCwyKWAlIGFyZSBjYXJyaWVkIG91dCBvbiByZXN0YXVyYW50cyB3aXRoIFNlYXRpbmcgMTMtNTAuIGByIHJvdW5kKChpbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUgZmlsdGVyKFNlYXRpbmcgPT0gJ1NlYXRpbmcgMC0xMicpICU+JSBucm93KCkpLyhpbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUgbnJvdygpKSoxMDAsMilgJSBhcmUgY2FycmllZCBvdXQgb24gcmVzdGF1cmFudHMgd2l0aCBTZWF0aW5nIDAtMTIgYW5kIGByIHJvdW5kKChpbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUgZmlsdGVyKFNlYXRpbmcgPT0gJ1NlYXRpbmcgNTEtMTUwJykgJT4lIG5yb3coKSkvKGluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JSBucm93KCkpKjEwMCwyKWAlIGFyZSBjYXJyaWVkIG91dCBvbiByZXN0YXVyYW50cyB3aXRoIFNlYXRpbmcgNTEtMTUwLiBSZW1haW5pbmcgcmVzdGF1cmFudCB0eXBlcyBhcmUgU2Nob29sIEx1bmNoIFByb2dyYW1zLCBNZWF0L1NlYWZvb2QsIEdyb2NlcnkgU3RvcmVzIC0gbm8gc2VhdGluZywgU2VhdGluZyAxNTEtMjUwIGFuZCBmZXcgbW9yZS4gIAogIC0gTWF4aW11bSByZXN0YXVyYW50cyBiZWluZyBpbnNwZWN0ZWQgYXJlIHVuZGVyIFJpc2sgQ2F0ZWdvcnkgSUlJICh3aGljaCBwcmVwYXJlIGZvb2QgZnJvbSBzY3JhdGNoIC0gYHIgcm91bmQoKGluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JSBmaWx0ZXIoUmlza19DYXRlZ29yeSA9PSAnUmlzayBDYXRlZ29yeSBJSUknKSAlPiUgbnJvdygpKS8oaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lIG5yb3coKSkqMTAwLDIpYCUpICAgIAogIC0gT3V0IG9mIGByIGluc3BlY3Rpb25fZGF0YSAlPiUgZ3JvdXBfYnkoUHJvZ3JhbV9JZGVudGlmaWVyLCBHcmFkZSkgJT4lIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lIG5yb3coKWAgcmVzdGF1cmFudHMsIGByIHJvdW5kKChpbnNwZWN0aW9uX2RhdGEgJT4lIGdyb3VwX2J5KFByb2dyYW1fSWRlbnRpZmllciwgR3JhZGUpICU+JSBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JSBmaWx0ZXIoR3JhZGUgPT0gMSkgJT4lIG5yb3coKSkvKGluc3BlY3Rpb25fZGF0YSAlPiUgZ3JvdXBfYnkoUHJvZ3JhbV9JZGVudGlmaWVyLCBHcmFkZSkgJT4lIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lIG5yb3coKSkqMTAwLDIpYCUgYXJlIGdyYWRlZCAxLCBgciByb3VuZCgoaW5zcGVjdGlvbl9kYXRhICU+JSBncm91cF9ieShQcm9ncmFtX0lkZW50aWZpZXIsIEdyYWRlKSAlPiUgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUgZmlsdGVyKEdyYWRlID09IDIpICU+JSBucm93KCkpLyhpbnNwZWN0aW9uX2RhdGEgJT4lIGdyb3VwX2J5KFByb2dyYW1fSWRlbnRpZmllciwgR3JhZGUpICU+JSBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JSBucm93KCkpKjEwMCwyKWAlIGFyZSBncmFkZWQgMiBhbmQgYHIgcm91bmQoKGluc3BlY3Rpb25fZGF0YSAlPiUgZ3JvdXBfYnkoUHJvZ3JhbV9JZGVudGlmaWVyLCBHcmFkZSkgJT4lIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lIGZpbHRlcihHcmFkZSA9PSAzKSAlPiUgbnJvdygpKS8oaW5zcGVjdGlvbl9kYXRhICU+JSBncm91cF9ieShQcm9ncmFtX0lkZW50aWZpZXIsIEdyYWRlKSAlPiUgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUgbnJvdygpKSoxMDAsMilgJSBhcmUgZ3JhZGVkIDMuIFdlIGRvIG5vdCBoYXZlIGdyYWRlcyBmb3IgYHIgcm91bmQoKGluc3BlY3Rpb25fZGF0YSAlPiUgZ3JvdXBfYnkoUHJvZ3JhbV9JZGVudGlmaWVyLCBHcmFkZSkgJT4lIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lIGZpbHRlcihHcmFkZSA9PSAnKE1pc3NpbmcpJykgJT4lIG5yb3coKSkvKGluc3BlY3Rpb25fZGF0YSAlPiUgZ3JvdXBfYnkoUHJvZ3JhbV9JZGVudGlmaWVyLCBHcmFkZSkgJT4lIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lIG5yb3coKSkqMTAwLDIpYCUgb2YgcmVzdGF1cmFudHMgQXMgbWVudGlvbmVkIGJlZm9yZSwgdGhlc2UgZ3JhZGVzIGFyZSBjYWxjdWxhdGVkIHdpdGhpbiB0aGUgc2FtZSB6aXBjb2Rlcy4gICAKCiMjIFVuaS12YXJpYXRlIGdyYXBoaWNhbCBFREEgCiAtIEhpc3RvZ3JhbXMgYW5kIEJveHBsb3RzIGZvciBxdWFudGl0YXRpdmUgdmFyaWFibGVzIC0gSW5zcGVjdGlvbiBTY29yZSBhbmQgVmlvbGF0aW9uIFBvaW50cyAgCiAtIEJhciBncmFwaHMgZm9yIGZhY3RvciB2YXJpYWJsZXMKCiMjIyBJbnNwZWN0aW9uIFNjb3JlICAKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBVbmktdmFyaWF0ZSBncmFwaGljYWwgYW5hbHlzaXMgb2YgcXVhbnRpdGF0aXZlIHZhcmlhYmxlIC0gaW5zcGVjdGlvbiBzY29yZQoKdW5pcXVlX2luc3BlY3Rpb25fZGF0YSA8LSBpbnNwZWN0aW9uX2RhdGFfbm90X2R1cApncmlkLmFycmFuZ2UodW5pcXVlX2luc3BlY3Rpb25fZGF0YSAlPiUgCiAgICAgICAgICAgICAgIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBJbnNwZWN0aW9uX1Njb3JlKSkgKyAKICAgICAgICAgICAgICAgZ2VvbV9oaXN0b2dyYW0oKSwKICAgICAgICAgICAgIHVuaXF1ZV9pbnNwZWN0aW9uX2RhdGEgJT4lIAogICAgICAgICAgICAgICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gMSwgeSA9IEluc3BlY3Rpb25fU2NvcmUpKSArIAogICAgICAgICAgICAgICBnZW9tX2JveHBsb3QoKSArIAogICAgICAgICAgICAgICBjb29yZF9mbGlwKCksCiAgICAgICAgICAgICBuY29sID0gMSkKYGBgCiAgCiAgCiAtIFRoZSBpbnNwZWN0aW9uIHNjb3JlIHNlZW1zIHRvIGJlIHNrZXdlZCB0b3dhcmRzIGxlZnQsIHRodXMgd2UgYXJlIGdvaW5nIHRvIGNvbnNpZGVyIG1lZGlhbiBhcyB0aGUgbWVhc3VyZSBvZiBjZW50cmFsIHRlbmRlbmN5ICAKIC0gVGhlcmUgYXJlIGEgbG90IG9mIG91dGxpZXJzIHdpdGggaW5zcGVjdGlvbiBzY29yZSBncmVhdGVyIHRoYW4gMjUKCiMjIyBWaW9sYXRpb24gUG9pbnRzICAKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBVbmktdmFyaWF0ZSBncmFwaGljYWwgYW5hbHlzaXMgb2YgcXVhbnRpdGF0aXZlIHZhcmlhYmxlIC0gdmlvbGF0aW9uIHBvaW50cwoKZ3JpZC5hcnJhbmdlKGluc3BlY3Rpb25fZGF0YSAlPiUgCiAgICAgICAgICAgICAgIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBWaW9sYXRpb25fUG9pbnRzKSkgKyAKICAgICAgICAgICAgICAgZ2VvbV9oaXN0b2dyYW0oKSwKICAgICAgICAgICAgIGluc3BlY3Rpb25fZGF0YSAlPiUgCiAgICAgICAgICAgICAgIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSAxLCB5ID0gVmlvbGF0aW9uX1BvaW50cykpICsgCiAgICAgICAgICAgICAgIGdlb21fYm94cGxvdCgpICsgCiAgICAgICAgICAgICAgIGNvb3JkX2ZsaXAoKSwKICAgICAgICAgICAgIG5jb2wgPSAxKQoKYGBgCgogLSBUaGVyZSBhcmUgZ2FwcyBpbiB0aGUgZGlzdHJpYnV0aW9uIG9mIHZpb2xhdGlvbiBwb2ludHMKIC0gTW9zdCBvZiB0aGUgaW5zcGVjdGlvbnMgaGFkIDAgdmlvbGF0aW9uIHBvaW50cywgZm9sbG93ZWQgYnkgNSBhbmQgMTAKIAoKIyMjIENpdHkgIApgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIFVuaS12YXJpYXRlIGdyYXBoaWNhbCBhbmFseXNpcyBvZiBmYWN0b3IgdmFyaWFibGUgLSBDaXR5Cmluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JSAKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gQ2l0eSkpICsgCiAgZ2VvbV9iYXIoKQpgYGAKCiAtIFRoZXJlIGFyZSBgciBsZW5ndGgodW5pcXVlKGluc3BlY3Rpb25fZGF0YSRDaXR5KSlgIGNpdGllcyBpbiB3aGljaCBpbnNwZWN0aW9ucyBhcmUgY2FycmllZCBvdXQgYnkgS2luZyBDb3VudHkKCiMjIyBaaXBjb2RlCmBgYHtyIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMgVW5pLXZhcmlhdGUgZ3JhcGhpY2FsIGFuYWx5c2lzIG9mIGZhY3RvciB2YXJpYWJsZSAtIFppcGNvZGUKaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lIAogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBaaXBDb2RlKSkgKyAKICBnZW9tX2JhcigpCmBgYAogCiAtIFRoZXJlIGFyZSBgciBsZW5ndGgodW5pcXVlKGluc3BlY3Rpb25fZGF0YSRaaXBDb2RlKSlgIHppcGNvZGVzIGluIHdoaWNoIGluc3BlY3Rpb25zIGFyZSBjYXJyaWVkIG91dCBieSBLaW5nIENvdW50eQogCiMjIyBJbnNwZWN0aW9uIFR5cGUgCmBgYHtyIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMgVW5pLXZhcmlhdGUgZ3JhcGhpY2FsIGFuYWx5c2lzIG9mIGZhY3RvciB2YXJpYWJsZSAtIEluc3BlY3Rpb24gVHlwZQppbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUgCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IEluc3BlY3Rpb25fVHlwZSkpICsgCiAgZ2VvbV9iYXIoKSArIAogIGNvb3JkX2ZsaXAoKQpgYGAKICAKIC0gTWF4aW11bSBpbnNwZWN0aW9ucyBiZWluZyBjYXJyaWVkIG91dCBpbiBLaW5nIENvdW50eSBhcmUgZm9yIEluc3BlY3Rpb24gLyBGaWVsZCBSZXZpZXcsIGZvbGxvd2VkIGJ5IENvbnN1bHRhdGlvbiBhbmQgRWR1Y2F0aW9uCiAtIFdlIGNhbiBsb29rIGF0IHdoYXQgJSBvZiByZXN0YXVyYW50cyByZXF1aXJlIHJldHVybiBpbnNwZWN0aW9uPwoKIyMjIEluc3BlY3Rpb24gUmVzdWx0IApgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIFVuaS12YXJpYXRlIGdyYXBoaWNhbCBhbmFseXNpcyBvZiBmYWN0b3IgdmFyaWFibGUgLSBJbnNwZWN0aW9uIFJlc3VsdAppbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gSW5zcGVjdGlvbl9SZXN1bHQpKSArIAogIGdlb21fYmFyKCkgKyAKICBjb29yZF9mbGlwKCkKYGBgCgogLSBNb3N0IG9mIHRoZSBpbnNwZWN0aW9ucyBjYXJyaWVkIG91dCB3ZXJlIHNhdGlzZmFjdG9yeSBmb2xsb3dlZCBieSB1bnNhdGlzZmFjdG9yeSBhbmQgY29tcGxldGUgIAogLSBXZSB3aWxsIGJlIGxvb2tpbmcgYXQgdGhlc2UgY2F0ZWdvcmllcyBmcm9tIGhlcmUgb24gc2luY2Ugd2UgZG8gbm90IGhhdmUgYSBsb3Qgb2YgZGF0YSBmb3Igb3RoZXIgY2F0ZWdvcmllcyAgCiAtIFdoYXQgZmFjdG9ycyBkb2VzIHRoZSBpbnNwZWN0aW9uIHJlc3VsdCBkZXBlbmQgb24/IFdoYXQgYXJlIHRoZSByYW5nZSBvZiBpbnNwZWN0aW9uIHNjb3JlcyBpbiB2YXJpb3VzIGNhdGVnb3JpZXMgZm9yIGluc3BlY3Rpb24gcmVzdWx0PyAgCgojIyMgSW5zcGVjdGlvbiBDbG9zZWQgQnVzaW5lc3MgCmBgYHtyIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMgVW5pLXZhcmlhdGUgZ3JhcGhpY2FsIGFuYWx5c2lzIG9mIGZhY3RvciB2YXJpYWJsZSAtIEluc3BlY3Rpb24gQ2xvc2VkIEJ1c2luZXNzCmluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JSAKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gSW5zcGVjdGlvbl9DbG9zZWRfQnVzaW5lc3MpKSArIAogIGdlb21fYmFyKCkgKyAKICBjb29yZF9mbGlwKCkKYGBgCgogLSBNb3N0IG9mIHRoZSB0aW1lcyB0aGUgcmVzdGF1cmFudCBkaWQgbm90IGNsb3NlCiAtIFdoYXQgY2F1c2VkIGEgcmVzdGF1cmFudCB0byBjbG9zZT8gCgojIyMgVmlvbGF0aW9uIFR5cGUKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBVbmktdmFyaWF0ZSBncmFwaGljYWwgYW5hbHlzaXMgb2YgZmFjdG9yIHZhcmlhYmxlIC0gVmlvbGF0aW9uIFR5cGUKaW5zcGVjdGlvbl9kYXRhICU+JSAKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gVmlvbGF0aW9uX1R5cGUpKSArIAogIGdlb21fYmFyKCkKYGBgCgogLSBUaGVyZSBhcmUgbW9yZSBSRUQgdmlvbGF0aW9ucyB0aGFuIEJMVUUuCiAtIEFsc28sIHJlc3RhdXJhbnRzIGhhdmUgbm90IHZpb2xhdGVkIG1heGltdW0gbnVtYmVyIG9mIHRpbWVzCgojIyMgVmlvbGF0aW9uIE51bWJlciAKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBVbmktdmFyaWF0ZSBncmFwaGljYWwgYW5hbHlzaXMgb2YgZmFjdG9yIHZhcmlhYmxlcyAtIFZpb2xhdGlvbiBOdW1iZXIgKFNpbWlsYXIgd291bGQgYmUgZm9yIHZpb2xhdGlvbiBkZXNjcmlwdGlvbikKaW5zcGVjdGlvbl9kYXRhICU+JSAKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gVmlvbGF0aW9uX051bWJlcikpICsgCiAgZ2VvbV9iYXIoKSArIAogIGNvb3JkX2ZsaXAoKQpgYGAKCiAtIFdlIGNhbiBsb29rIGF0IHdoaWNoIHZpb2xhdGlvbiBudW1iZXJzIGFyZSBvY2N1cnJpbmcgdGhlIG1vc3Q/IEFyZSB0aGVyZSBwYXR0ZXJucyBvZiB2aW9sYXRpb24gbnVtYmVycyBkdXJpbmcgZGlmZmVyZW50IG1vbnRocz8KIC0gU2FtZSBkaXN0cmlidXRpb24gZm9yIHZpb2xhdGlvbiBkZXNjcmlwdGlvbgogIAojIyMgU2VhdGluZwpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIFVuaS12YXJpYXRlIGdyYXBoaWNhbCBhbmFseXNpcyBvZiBmYWN0b3IgdmFyaWFibGUgLSBTZWF0aW5nCmluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JSAKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gU2VhdGluZykpICsgCiAgZ2VvbV9iYXIoKSArIAogIGNvb3JkX2ZsaXAoKQpgYGAKCiAtIE1vc3Qgb2YgdGhlIHJlc3RhdXJhbnRzIGJlaW5nIGluc3BlY3RlZCBmb3IgZm9vZCBzYWZldHkgaW4gS2luZyBDb3VudHkgYXJlIHdpdGggU2VhdGluZyAxMyAtIDUwLCBmb2xsb3dlZCBieSBTZWF0aW5nIDUxIC0gMTUwLCBmb2xsb3dlZCBieSBTZWF0aW5nIDAgLSAxMiAgCiAtIERvZXMgdGhlIHZpb2xhdGlvbnMgdmFyeSBieSBTZWF0aW5nIHR5cGVzPwogLSBBcmUgdGhlIGluc3BlY3Rpb24gc2NvcmVzIGhpZ2hlciBmb3IgbW9yZSBzZWF0aW5nIHJlc3RhdXJhbnRzPwogIAojIyMgUmlzayBDYXRlZ29yeQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIFVuaS12YXJpYXRlIGdyYXBoaWNhbCBhbmFseXNpcyBvZiBmYWN0b3IgdmFyaWFibGUgLSBSaXNrIENhdGVnb3J5Cmluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JSAKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gUmlza19DYXRlZ29yeSkpICsgCiAgZ2VvbV9iYXIoKSArIAogIGNvb3JkX2ZsaXAoKQpgYGAKCiAtIE1heGltdW0gcmVzdGF1cmFudHMgYmVpbmcgaW5zcGVjdGVkIGZvciBmb29kIHNhZmV0eSBmYWxsIHVuZGVyIFJpc2sgQ2F0ZWdvcnkgSUlJIHdoaWNoIG1lYW5zIHRoZXkgcHJlcGFyZSBmb29kIGZyb20gc2NyYXRjaAogIAojIyMgR3JhZGUKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBVbmktdmFyaWF0ZSBncmFwaGljYWwgYW5hbHlzaXMgb2YgZmFjdG9yIHZhcmlhYmxlIC0gR3JhZGUKaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lIAogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBHcmFkZSkpICsgCiAgZ2VvbV9iYXIoKSArIAogIGNvb3JkX2ZsaXAoKQpgYGAKCiAtIE1vc3Qgb2YgdGhlIHJlc3RhdXJhbnRzIGFyZSBncmFkZWQgMSBieSBjb3VudHkKIC0gV2UgaGF2ZSBhIGxvdCBvZiBtaXNzaW5nIGRhdGEgZm9yIGdyYWRlcwoKIyMjIEZpbmRpbmdzCiAtIFRoZXJlIGFyZSBtb3JlIG9mIFJlZCB2aW9sYXRpb25zIHRoYW4gYmx1ZQogLSBBbG1vc3QgaGFsZiBvZiB0aGUgaW5zcGVjdGlvbnMgYXJlIGNhcnJpZWQgb3V0IGluIFNlYXR0bGUKIC0gTW9zdCBvZiB0aGUgaW5zcGVjdGlvbnMgYXJlIHJvdXRpbmUgYW5kIGZpZWxkIHJldmlld3MKIAojIyMgUXVlc3Rpb25zCiAtIERvZXMgaW5zcGVjdGlvbiBzY29yZSB2YXJpZXMgd2l0aCBDaXRpZXM/CiAtIERvZXMgdmlvbGF0aW9uIHBvaW50cyBkaXN0cmlidXRpb24gc3RheSB0aGUgc2FtZSBhY3Jvc3MgQ2l0aWVzPwogLSBXaGF0IGlzIHRoZSByZWxhdGlvbiBiZXR3ZWVuIGluc3BlY3Rpb24gcmVzdWx0IGFuZCBpbnNwZWN0aW9uIHNjb3JlPwogLSBJcyB0aGVyZSBhbnkgc2VwY2lmaWMgdHlwZSBvZiB2aW9sYXRpb24gb2N1cnJpbmcgaW4gcGFydGljdWxhciBhcmVhIG9yIHBhcnRpY3VsYXIgbW9udGg/CiAtIEhvdyBtYW55IHJlc3RhdXJhbnRzIG5lZWQgcmV0dXJuIGluc3BlY3Rpb24/CiAtIEhvdyBhcmUgcmVzdGF1cmFudHMgcGVyZm9ybWluZyBvdmVyIHRpbWU/CiAtIFdoYXQgY2F1c2VkIHRoZSByZXN0YXVyYW50cyB0byBjbG9zZT8KIC0gRG9lcyBtb3JlIFNlYXRpbmdzIGluY3JlYXNlIHZpb2xhdGlvbnMvaW5zcGVjdGlvbiBzY29yZT8KIC0gV2hhdCBjYXVzZWQgdGhlIHJlc3RhdXJhbnQgdG8gYmUgZ3JhZGVkIDE/CgojIyBNdWx0aS12YXJpYXRlIG5vbi1ncmFwaGljYWwgYW5hbHlzaXMKCiMjIyBJbnNwZWN0aW9uIFR5cGUgeCBJbnNwZWN0aW9uIFJlc3VsdAoKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lIAogIHRhYnlsKEluc3BlY3Rpb25fVHlwZSwgSW5zcGVjdGlvbl9SZXN1bHQpICU+JSAKICBhZG9ybl90b3RhbHMod2hlcmUgPSBjKCJyb3ciLCAiY29sIikpICU+JSAKICBhZG9ybl9wZXJjZW50YWdlcygicm93IikgJT4lCiAgYWRvcm5fcGN0X2Zvcm1hdHRpbmcoKSAlPiUKICBhZG9ybl9ucygpICAlPiUgCiAgc2VsZWN0KGMoJ0luc3BlY3Rpb25fVHlwZScsJ0NvbXBsZXRlJywnU2F0aXNmYWN0b3J5JywnVW5zYXRpc2ZhY3RvcnknKSkgJT4lCiAga2FibGUoKSU+JSBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgZnVsbF93aWR0aCA9IEYpCmBgYAoKIC0gUm91dGluZSBpbnNwZWN0aW9ucyBoYXZlIG1vc3RseSBzYXRpc2ZhY3RvcnkgcmVzdWx0cyBmb2xsb3dlZCBieSB1bnNhdGlzZmFjdG9yeQogLSBDb25zdWx0YXRpb24vRWR1Y2F0aW9uIGluc3BlY3Rpb25zIGhhdmUgbW9zdGx5IHJlc3VsdHMgYXMgJ0NvbXBsZXRlJwogLSBSZXR1cm4gaW5zcGVjdGlvbnMgaGF2ZSBtb3N0bHkgYmVlbiBzYXRpc2ZhY3RvcnkgZm9sbHdlZCBieSB1bnNhdGlzZmFjdG9yeQogLSBXaGF0IGNhdXNlcyBhIHJldHVybiBpbnNwZWN0aW9uIHRvIGJlIHVuc2F0aXNmYWN0b3J5PwogLSBIb3cgbWFueSByZXN0YXVyYW50cyBnZXQgcmV0dXJuIGluc3BlY3Rpb25zIC8gdW5zYXRpc2ZhY3RvcnkgcmVzdWx0cyBldmVyeSB5ZWFyPwogCiMjIyBJbnNwZWN0aW9uIFR5cGUgeCBDbG9zZWQgQnVzaW5lc3MKCmBgYHtyfQppbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUgCiAgdGFieWwoSW5zcGVjdGlvbl9UeXBlLCBJbnNwZWN0aW9uX0Nsb3NlZF9CdXNpbmVzcykgJT4lIAogIGFkb3JuX3RvdGFscyh3aGVyZSA9IGMoInJvdyIsICJjb2wiKSkgJT4lIAogIGFkb3JuX3BlcmNlbnRhZ2VzKCJyb3ciKSAlPiUKICBhZG9ybl9wY3RfZm9ybWF0dGluZygpICU+JQogIGFkb3JuX25zKCkgJT4lCiAgc2VsZWN0KGMoMSwyLDMpKSAlPiUKICBrYWJsZSgpJT4lIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRikKYGBgCgogLSBJdCBsb29rcyBsaWtlIHJlc3RhdXJhbnRzIGFyZSB0aHJlZSB0aW1lcyBtb3JlIGxpa2VseSB0byBiZSBjbG9zZWQgaW4gcmV0dXJuIGluc3BlY3Rpb24gdGhhbiByb3V0aW5lIGluc3BlY3Rpb24gIAogCiMjIyBJbnNwZWN0aW9uIFJlc3VsdCB4IENsb3NlZCBCdXNpbmVzcwoKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lIAogIHRhYnlsKEluc3BlY3Rpb25fUmVzdWx0LCBJbnNwZWN0aW9uX0Nsb3NlZF9CdXNpbmVzcykgJT4lIAogIGFkb3JuX3RvdGFscyh3aGVyZSA9IGMoInJvdyIsICJjb2wiKSkgJT4lIAogIGFkb3JuX3BlcmNlbnRhZ2VzKCJyb3ciKSAlPiUKICBhZG9ybl9wY3RfZm9ybWF0dGluZygpICU+JQogIGFkb3JuX25zKCkgJT4lIAogIGZpbHRlcihJbnNwZWN0aW9uX1Jlc3VsdCAlaW4lIGMoIkNvbXBsZXRlIiwiU2F0aXNmYWN0b3J5IiwiVW5zYXRpc2ZhY3RvcnkiLCJUb3RhbCIpKSAlPiUKICBzZWxlY3QoYygxLDIsMykpICU+JQogIGthYmxlKCklPiUga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGKQpgYGAKCiAtIEFzIGV4cGVjdGVkLCA5MSUgb2YgdGhlIHJlc3RhdXJhbnRzIGNsb3NlZCBoYWQgVW5zYXRpc2ZhY3RvcnkgaW5zcGVjdGlvbnMKIAojIyMgU2VhdGluZyB4IEluc3BlY3Rpb24gUmVzdWx0CgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQppbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUgCiAgdGFieWwoU2VhdGluZywgSW5zcGVjdGlvbl9SZXN1bHQpICU+JSAKICBhZG9ybl90b3RhbHMod2hlcmUgPSBjKCJyb3ciLCAiY29sIikpICU+JSAKICBhZG9ybl9wZXJjZW50YWdlcygicm93IikgJT4lCiAgYWRvcm5fcGN0X2Zvcm1hdHRpbmcoKSAgJT4lCiAgYWRvcm5fbnMoKSAlPiUgc2VsZWN0KGMoIkNvbXBsZXRlIiwiU2F0aXNmYWN0b3J5IiwiVW5zYXRpc2ZhY3RvcnkiLCJUb3RhbCIpKSAlPiUKIGthYmxlKCklPiUga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGKQpgYGAKCiAtIEFzIHRoZSBTZWF0aW5nIGluY3JlYXNlcywgdGhlcmUgaXMgbW9yZSBwZXJjZW50YWdlIG9mIHVuc2F0aXNmYWN0b3J5IHJlc3VsdHMgd2l0aGluIHRoZSBncm91cAogLSBNYXkgYmUgc21hbGwgcmVzdGF1cmFudHMgaGF2ZSBiZXR0ZXIgcXVhbGl0eSBjb250cm9sICAKIC0gQXMgbWVudGlvbmVkIGJlZm9yZSwgd2UgYXJlIG9ubHkgbG9va2luZyBhdCBTYXRpc2ZhY3RvcnkvVW5zYXRpc2ZhY3RvcnkgYW5kIENvbXBsZXRlIGluc3BlY3Rpb24gcmVzdWx0cyAgCgojIyMgU2VhdGluZyB4IEluc3BlY3Rpb24gVHlwZQoKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lIAogIHRhYnlsKFNlYXRpbmcsIEluc3BlY3Rpb25fVHlwZSkgJT4lIAogIGFkb3JuX3RvdGFscyh3aGVyZSA9IGMoInJvdyIsICJjb2wiKSkgJT4lIAogIGFkb3JuX3BlcmNlbnRhZ2VzKCJyb3ciKSAlPiUKICBhZG9ybl9wY3RfZm9ybWF0dGluZygpICU+JQogIGFkb3JuX25zKCkgJT4lIAogIHNlbGVjdChjKDEsMiwzLDQpKSU+JQogIGthYmxlKCklPiUga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGKQpgYGAKCiAtIEFnYWluLCByZXN0YXVyYW50cyB3aXRoIG1vcmUgc2VhdGluZyBoYXZlIG1vcmUgcmVxdWlyZW1lbnQgb2YgcmV0dXJuIGluc3BlY3Rpb25zCgojIyMgIFNlYXRpbmcgeCBJbnNwZWN0aW9uIENsb3NlZCBCdXNpbmVzcwoKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lIAogIHRhYnlsKFNlYXRpbmcsIEluc3BlY3Rpb25fQ2xvc2VkX0J1c2luZXNzKSAlPiUgCiAgYWRvcm5fdG90YWxzKHdoZXJlID0gYygicm93IiwgImNvbCIpKSAlPiUgCiAgYWRvcm5fcGVyY2VudGFnZXMoInJvdyIpICU+JQogIGFkb3JuX3BjdF9mb3JtYXR0aW5nKCkgJT4lCiAgYWRvcm5fbnMoKSAlPiUgCiAgc2VsZWN0KGMoMSwyLDMpKSAlPiUKICBrYWJsZSgpJT4lIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRikKYGBgCgogLSBMb29rcyBsaWtlIG1vYmlsZSBmb29kIHVuaXRzIGdldCBjbG9zZWQgYSBsb3QgCiAKIyMjIFNlYXRpbmcgeCBSaXNrIENhdGVnb3J5CgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQppbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUgCiAgdGFieWwoU2VhdGluZywgUmlza19DYXRlZ29yeSkgJT4lIAogIGFkb3JuX3RvdGFscyh3aGVyZSA9IGMoInJvdyIsICJjb2wiKSkgJT4lIAogIGFkb3JuX3BlcmNlbnRhZ2VzKCJyb3ciKSAlPiUKICBhZG9ybl9wY3RfZm9ybWF0dGluZygpICU+JQogIGFkb3JuX25zKCkgJT4lIAogIHNlbGVjdChjKDEsMiwzLDQpKSU+JQogIGthYmxlKCklPiUga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGKQpgYGAKCiAtIEdyb2NlcnkgU3RvcmVzIGZvcm0gbW9yZSB0aGFuIGhhbGYgb2YgdGhlIFJpc2sgQ2F0ZWdvcnkgSSByZXN0YXVyYW50cyAgCiAtIFJpc2sgQ2F0ZWdvcnkgSUkgYXJlIGRvbWluYXRlZCBieSByZXN0YXVyYW50cyB3aXRoIFNlYXRpbmcgMC0xMiBhbmQgMTMtNTAKCiMjIyAgSW5zcGVjdGlvbiBSZXN1bHQgeCBWaW9sYXRpb24gVHlwZSAKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9Cmluc3BlY3Rpb25fZGF0YSAlPiUgCiAgdGFieWwoSW5zcGVjdGlvbl9SZXN1bHQsIFZpb2xhdGlvbl9UeXBlKSAlPiUgCiAgYWRvcm5fdG90YWxzKHdoZXJlID0gYygicm93IiwgImNvbCIpKSAlPiUgCiAgYWRvcm5fcGVyY2VudGFnZXMoInJvdyIpICU+JQogIGFkb3JuX3BjdF9mb3JtYXR0aW5nKCkgJT4lCiAgYWRvcm5fbnMoKSAlPiUKICBmaWx0ZXIoSW5zcGVjdGlvbl9SZXN1bHQgJWluJSBjKCdDb21wbGV0ZScsJ1NhdGlzZmFjdG9yeScsJ1Vuc2F0aXNmYWN0b3J5JykpICU+JSAKICBrYWJsZSgpJT4lIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRikKYGBgCgogLSBJbnNwZWN0aW9uIHJlc3VsdHMgYXJlIHVuc2F0aXNmYWN0b3J5IHdoZW4gdGhlcmUgYXJlIFJFRCB2aW9sYXRpb25zIG1vc3RseQogLSBJbnNwZWN0aW9uIHJlc3VsdHMgYXJlIGNvbXBsZXRlIHdoZW4gdGhlcmUgYXJlIG5vIHZpb2xhdGlvbnMgbW9zdGx5CgojIyMgU2VhdGluZyB4IFZpb2xhdGlvbiBUeXBlCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQppbnNwZWN0aW9uX2RhdGEgJT4lIAogIHRhYnlsKFNlYXRpbmcsIFZpb2xhdGlvbl9UeXBlKSAlPiUgCiAgYWRvcm5fdG90YWxzKHdoZXJlID0gYygicm93IiwgImNvbCIpKSAlPiUgCiAgYWRvcm5fcGVyY2VudGFnZXMoInJvdyIpICU+JQogIGFkb3JuX3BjdF9mb3JtYXR0aW5nKCkgJT4lCiAgYWRvcm5fbnMoKSAlPiUKICBzZWxlY3QoMSwyLDMsNCkgJT4lCiAga2FibGUoKSU+JSBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgZnVsbF93aWR0aCA9IEYpCgpgYGAKCiAtIEl0IGFwcGVhcnMgdGhhdCBhcyB0aGUgc2VhdGluZyBpbmNyZWFzZXMsIHRoZSBwcm9wb3J0aW9uIG9mIHJlZCB2aW9sYXRpb25zIGluY3JlYXNlIAoKIyMjIFZpb2xhdGlvbiBUeXBlIHggUmlzayBDYXRlZ29yeQoKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KaW5zcGVjdGlvbl9kYXRhICU+JSAKICB0YWJ5bChWaW9sYXRpb25fVHlwZSwgUmlza19DYXRlZ29yeSkgJT4lIAogIGFkb3JuX3RvdGFscyh3aGVyZSA9IGMoInJvdyIsICJjb2wiKSkgJT4lIAogIGFkb3JuX3BlcmNlbnRhZ2VzKCJyb3ciKSAlPiUKICBhZG9ybl9wY3RfZm9ybWF0dGluZygpICU+JQogIGFkb3JuX25zKCkgJT4lIHNlbGVjdChjKDEsMiwzLDQpKSAlPiUgCiAga2FibGUoKSU+JSBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgZnVsbF93aWR0aCA9IEYpCgpgYGAKCiAtIFJlc3RhdXJhbnRzIHVuZGVyIFJpc2sgQ2F0ZWdvcnkgSUlJIGhhdmUgYWxtb3N0IHNpbWlsYXIgcGVyY2VudGFnZSBvZiByZWQgYW5kIGJsdWUgdmlvbGF0aW9ucwogCiMjIyBDaXR5IHggVmlvbGF0aW9uIFR5cGUKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9Cmluc3BlY3Rpb25fZGF0YSAlPiUgCiAgdGFieWwoQ2l0eSwgVmlvbGF0aW9uX1R5cGUpICU+JSAKICBhZG9ybl90b3RhbHMod2hlcmUgPSBjKCJyb3ciLCAiY29sIikpICU+JSAKICBhZG9ybl9wZXJjZW50YWdlcygicm93IikgJT4lCiAgYWRvcm5fcGN0X2Zvcm1hdHRpbmcoKSAlPiUKICBhZG9ybl9ucygpICU+JQogIGZpbHRlcihDaXR5ICVpbiUgYygnU0VBVFRMRScsJ0JFTExFVlVFJywnS0VOVCcsJ0ZFREVSQUwgV0FZJywnUkVOVE9OJykpICU+JSAKICBzZWxlY3QoYygxLDIsMyw0KSkgJT4lIAogIGthYmxlKCklPiUga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGKQoKYGBgCgogLSBXZSBsb29rZWQgYXQgdGhlIHRvcCA1IGNpdGllcyB3aXRoIG1heGltdW0gbnVtYmVyIG9mIHJlc3RhdXJhbnRzIGFuZCByZWFsaXplZCB0aGF0IEJlbGxldnVlIGhhcyBtb3JlIHBlcmNlbnRhZ2Ugb2YgUmVkIFZpb2xhdGlvbnMgdGhhbiBOb25lIHdoaWNoIGlzIHRoZSBvcHBvc2l0ZSBvZiBvdGhlcnMgIAogLSBEb2VzIHRoaXMgcGF0dGVybiBvZiBCZWxsZXZ1ZSByZW1haW4gdGhlIHNhbWUgYWNyb3NzIHRoZSB5ZWFycz8gIAogLSBEb2VzIHRoaXMgcGF0dGVybiBvZiBvdGhlciBjaXRpZXMgcmVtYWluIHRoZSBzYW1lIGFjcm9zcyB0aGUgeWVhcnM/ICAKCiMjIyBDb3JyZWxhdGlvbiBUYWJsZQoKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KaW5zcGVjdGlvbl9kYXRhICU+JSAKICBncm91cF9ieShJbnNwZWN0aW9uX1NlcmlhbF9OdW0sIEluc3BlY3Rpb25fU2NvcmUpICU+JSAKICBzdW1tYXJpc2UocG9pbnRzID0gc3VtKFZpb2xhdGlvbl9Qb2ludHMpKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBzZWxlY3QoSW5zcGVjdGlvbl9TY29yZSwgcG9pbnRzKSAlPiUgCiAgY29yKCkKYGBgCgotIFdlIGNhbiBzZWUgdGhhdCBpbnNwZWN0aW9uIHNjb3JlIGlzIHZlcnkgY2xvc2VseSByZWxhdGVkIHRvIHZpb2xhdGlvbiBwb2ludHMgYmVjYXVzZSBldmVyeSBzY29yZSBpcyBhIHN1bSBvZiBpbmRlcGVuZGVudCB2aW9sYXRpb24gcG9pbnRzIGdyb3VwZWQgYnkgaW5zcGVjdGlvbiBzZXJpYWwgbnVtYmVyCgorIF9fRmluZGluZ3MgYW5kIFF1ZXN0aW9uc19fCiAgLSBXZSBmb3VuZCBvdXQgdGhhdCByZXN0YXVyYW50cyB3ZXJlIGNsb3NlZCBvbiByZXR1cm4gaW5zcGVjdGlvbnMgIAogIC0gQXMgdGhlIFNlYXRpbmcgaW5jcmVhc2VzLCBwcm9wb3J0aW9uIG9mIHJlZCB2aW9sYXRpb25zIGFuZCByZXR1cm4gaW5zcGVjdGlvbnMgaW5jcmVhc2UgIAogIC0gSW5zcGVjdGlvbiBTY29yZSBhbmQgVmlvbGF0aW9uIFBvaW50cyBhcmUgdmVyeSBzdHJvbmdseSByZWxhdGVkIG9idmlvdXNseSAgCiAgLSBXaGVuIGxvb2tpbmcgYXQgdGhlIHRvcCA1IGNpdGllcyB3aXRoIG1vc3QgcmVzdGF1cmFudHMgaW4gS2luZyBDb3VudHksIHdlIG9ic2VydmVkIHRoYXQgQmVsbGV2dWUgaGFzIG1vcmUgb2YgcmVkIHZpb2xhdGlvbnMgdGhhbiBibHVlICAKICAtIERvZXMgdGhlIHRyZW5kIG9mIFJlZC9CbHVlIHZpb2xhdGlvbnMgcmVtYWluIHRoZSBzYW1lIGZvciBjaXRpZXMgYWNyb3NzIHRoZSB5ZWFycz8KICAKIyMgTXVsdGktdmFyaWF0ZSBncmFwaGljYWwgYW5hbHlzaXMKCiMjIyBOdW1iZXIgb2YgaW5zcGVjdGlvbnMgZXZlcnkgeWVhcgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQppbnNwZWN0aW9uX3llYXIgPC0gaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lIAogIGdyb3VwX2J5KFllYXIpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpCgogaW5zcGVjdGlvbl95ZWFyJT4lCiAgZmlsdGVyKFllYXIhPScyMDE5JykgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeSA9IGNvdW50LCB4ID0gWWVhcikpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fbGluZShncm91cCA9IDEpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgCmBgYAogCiAtIEV4Y2x1ZGVkIDIwMTkgZGF0YSBiZWNhdXNlIGl0cyBub3QgZm9yIHRoZSBjb21wbGV0ZSB5ZWFyCiAtIFRoZSBudW1iZXIgb2YgaW5zcGVjdGlvbnMgaGF2ZSBiZWVuIGluY3JlYXNpbmcgZXZlcnkgeWVhciBleGNlcHQgZm9yIDIwMTUgd2hlcmUgdGhlcmUgd2FzIGEgZHJvcAogLSBUaGUgbnVtYmVyIG9mIGluc3BlY3Rpb25zIGluIDIwMTUgZGVjbGluZWQgYnkgYHIgcm91bmQoLShpbnNwZWN0aW9uX3llYXIkY291bnRbMTBdIC0gaW5zcGVjdGlvbl95ZWFyJGNvdW50WzldKS9pbnNwZWN0aW9uX3llYXIkY291bnRbOV0qMTAwLDIpYCUgYXMgY29tcGFyZWQgdG8gMjAxNCAKIC0gVGhlIG51bWJlciBvZiBpbnNwZWN0aW9ucyBpbiAyMDE3IGluY3JlYXNlZCBieSBgciByb3VuZCgoaW5zcGVjdGlvbl95ZWFyJGNvdW50WzEyXSAtIGluc3BlY3Rpb25feWVhciRjb3VudFsxMV0pL2luc3BlY3Rpb25feWVhciRjb3VudFsxMV0qMTAwLDIpYCUgYXMgY29tcGFyZWQgdG8gMjAxNiB3aGljaCBmdXJ0aGVyIGluY3JlYXNlZCBieSBgciByb3VuZCgoaW5zcGVjdGlvbl95ZWFyJGNvdW50WzEzXSAtIGluc3BlY3Rpb25feWVhciRjb3VudFsxMl0pL2luc3BlY3Rpb25feWVhciRjb3VudFsxMl0qMTAwLDIpYCUgaW4gMjAxOAoKIyMjIE51bWJlciBvZiB1bmlxdWUgcmVzdGF1cmFudHMgYmVpbmcgaW5zcGVjdGVkIGV2ZXJ5IHllYXIKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KdW5pcXVlX2J1c2luZXNzX2luc3BlY3Rpb25feWVhciA8LSBpbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUgCiAgZ3JvdXBfYnkoWWVhcikgJT4lIAogIHN1bW1hcmlzZShjb3VudF9idXNpbmVzc2VzID0gbl9kaXN0aW5jdChCdXNpbmVzc19JRCkpCgp1bmlxdWVfYnVzaW5lc3NfaW5zcGVjdGlvbl95ZWFyICU+JQogIGZpbHRlcihZZWFyIT0nMjAxOScpICU+JQogIGdncGxvdChtYXBwaW5nID0gYWVzKHkgPSBjb3VudF9idXNpbmVzc2VzLCB4ID0gWWVhcikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9saW5lKGdyb3VwID0gMSkgCmBgYAogCiAtIE51bWJlciBvZiB1bmlxdWUgcmVzdGF1cmFudHMgYmVpbmcgaW5zcGVjdGVkIGluY3JlYXNlZCBieSBgciByb3VuZCggKHVuaXF1ZV9idXNpbmVzc19pbnNwZWN0aW9uX3llYXIkY291bnRfYnVzaW5lc3Nlc1sxMF0tdW5pcXVlX2J1c2luZXNzX2luc3BlY3Rpb25feWVhciRjb3VudF9idXNpbmVzc2VzWzldKS91bmlxdWVfYnVzaW5lc3NfaW5zcGVjdGlvbl95ZWFyJGNvdW50X2J1c2luZXNzZXNbOV0qMTAwLDIpYCUgaW4gMjAxNSBhcyBjb21wYXJlZCB0byAyMDE0IGJ1dCB0aGUgZGVjbGluZSBvZiBudW1iZXIgb2YgaW5zcGVjdGlvbnMgY291bGQgbWVhbiB0aGVyZSB3YXMgYSBkZWNsaW5lIGluIG51bWJlciBvZiBpbnNwZWN0aW9ucyBwZXIgcmVzdGF1cmFudAogLSBPbiB0aGUgY29udHJhcnkgaW4gMjAxNywgdGhlIHJpc2UgaW4gbnVtYmVyIG9mIHVuaXF1ZSByZXN0YXVyYW50cyBiZWluZyBpbnNwZWN0ZWQgd2FzIGByIHJvdW5kKCAodW5pcXVlX2J1c2luZXNzX2luc3BlY3Rpb25feWVhciRjb3VudF9idXNpbmVzc2VzWzEyXS11bmlxdWVfYnVzaW5lc3NfaW5zcGVjdGlvbl95ZWFyJGNvdW50X2J1c2luZXNzZXNbMTFdKS91bmlxdWVfYnVzaW5lc3NfaW5zcGVjdGlvbl95ZWFyJGNvdW50X2J1c2luZXNzZXNbMTFdKjEwMCwyKWAlIGJ1dCB0aGUgdG90YWwgbnVtYmVyIG9mIGluc3BlY3Rpb25zIGluY3JlYXNlZCBhdCBhIG11Y2ggaGlnaGVyIHJhdGUsIHdoaWNoIGNvdWxkIGltcGx5IHRoYXQgdGhlcmUgd2VyZSBpbmNyZWFzZSBpbiBudW1iZXIgb2YgaW5zcGVjdGlvbnMgcGVyIHJlc3RhdXJhbnQKIAojIyMgTnVtYmVyIG9mIGluc3BlY3Rpb25zIHBlciByZXN0YXVyYW50CgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQppbnNwZWN0aW9uX3Blcl9idXNpbmVzcyA8LSBkYXRhLmZyYW1lKCJZZWFyIiA9IGluc3BlY3Rpb25feWVhciRZZWFyLCAicmF0aW8iID0gaW5zcGVjdGlvbl95ZWFyJGNvdW50IC8gdW5pcXVlX2J1c2luZXNzX2luc3BlY3Rpb25feWVhciRjb3VudF9idXNpbmVzc2VzKQoKYXMuZGF0YS5mcmFtZShpbnNwZWN0aW9uX3Blcl9idXNpbmVzcykgJT4lCiAgZmlsdGVyKFllYXIgIT0nMjAxOScpICU+JQogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBZZWFyLCB5ID0gcmF0aW8pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fbGluZShncm91cCA9IDEpCmBgYAoKIC0gQXMgbWVudGlvbmVkIGFib3ZlLCB3ZSBjYW4gc2VlIGEgY2xlYXIgZGVjbGluZSBpbiB0aGUgbnVtYmVyIG9mIGluc3BlY3Rpb25zIHBlciByZXN0YXVyYW50IGluIDIwMTUsIGNvbnRpbnVlZCB0byAyMDE2IGFzIHdlbGwKIC0gVGhlIG51bWJlciBvZiBpbnNwZWN0aW9ucyBwZXIgcmVzdGF1cmFudCBpbmNyZWFzZWQgdG8gYHIgcm91bmQoaW5zcGVjdGlvbl9wZXJfYnVzaW5lc3MkcmF0aW9bMTNdKWAgaW4gMjAxNwogLSBUaGVyZSBpcyBhIGNsZWFyIGRlY2xpbmUgaW4gbnVtYmVyIG9mIGluc3BlY3Rpb25zIHBlciByZXN0YXVyYW50IGZyb20gMjAwNiB0byAyMDE4CiAKIyMjIFBlcmNlbnRhZ2Ugb2YgcmVzdGF1cmFudHMgcmVxdWlyaW5nIHJldHVybiBpbnNwZWN0aW9uCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpyZXR1cm5faW5zcGVjdGlvbnMgPC0gaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lIAogIGdyb3VwX2J5KFllYXIsIEJ1c2luZXNzX0lEKSU+JSAKICBzdW1tYXJpc2UoY291bnQ9IGxlbmd0aCh3aGljaChJbnNwZWN0aW9uX1R5cGUgPT0gIlJldHVybiBJbnNwZWN0aW9uIikpKSAlPiUKICBmaWx0ZXIoY291bnQgPiAwKSAlPiUKICBncm91cF9ieShZZWFyKSAlPiUKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpCgpyZXR1cm5faW5zcGVjdGlvbnMkcmF0aW8gPC0gcmV0dXJuX2luc3BlY3Rpb25zJGNvdW50L3VuaXF1ZV9idXNpbmVzc19pbnNwZWN0aW9uX3llYXIkY291bnRfYnVzaW5lc3NlcwoKcmV0dXJuX2luc3BlY3Rpb25zICU+JQogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBZZWFyLCB5ID0gcmF0aW8pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fbGluZShncm91cCA9IDEpCgpgYGAKCiAtIEluY2x1ZGVkIDIwMTkgYXMgd2VsbCBiZWNhdXNlIHdlIGFyZSBjYWxjdWxhdGluZyBwZXJjZW50YWdlcyAgCiAtIEluIDIwMTQsIGByIHJvdW5kKHJldHVybl9pbnNwZWN0aW9ucyRyYXRpb1s5XSoxMDAsMilgJSBvZiByZXN0YXVyYW50cyBuZWVkZWQgcmV0dXJuIGluc3BlY3Rpb24gd2hpY2ggd2FzIGEgaHVnZSBqdW1wIGZyb20gMjAxMy4gMjAxNCB3YXMgdGhlIHllYXIgd2hlbiB0aGVyZSB3YXMgYSBtYWpvciBmb29kIGJvcm5lIGlsbGVzcyBvdXRicmVhay4gVGhlIHBlcmNlbnRhZ2UgaW5jcmVhc2VkIHRvIGByIHJvdW5kKHJldHVybl9pbnNwZWN0aW9ucyRyYXRpb1sxMF0qMTAwLDIpYCUgaW4gMjAxNSAgCiAtIEl0IHN0YXJ0ZWQgdG8gZGVjbGluZSBpbiAyMDE2IGFuZCBoYXMgYmVlbiBzaW5jZSB0aGVuICAKCiMjIyBOdW1iZXIgb2YgdmlvbGF0aW9ucyBwZXIgcmVzdGF1cmFudCBldmVyeSB5ZWFyCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQp2aW9sYXRpb25zX3llYXIgPC0gaW5zcGVjdGlvbl9kYXRhICU+JSAKICBncm91cF9ieShZZWFyKSAlPiUgCiAgZmlsdGVyKFZpb2xhdGlvbl9Qb2ludHMgIT0gMCkgJT4lCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAKCnZpb2xhdGlvbnNfeWVhciRyYXRpbyA8LSB2aW9sYXRpb25zX3llYXIkY291bnQgLyB1bmlxdWVfYnVzaW5lc3NfaW5zcGVjdGlvbl95ZWFyJGNvdW50X2J1c2luZXNzZXMKCnZpb2xhdGlvbnNfeWVhciAlPiUgCiAgZmlsdGVyKFllYXIhPScyMDE5JykgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeSA9IHJhdGlvLCB4ID0gWWVhcikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9saW5lKGdyb3VwID0gMSkKYGBgCgogLSBUaGVyZSB3YXMgYSBodWdoIGp1bXAgaW4gMjAxNChpbGxuZXNzIG91dGJyZWFrKSwgdGhlIG51bWJlciBvZiB2aW9sYXRpb25zIHBlciByZXN0YXVyYW50IGluY3JlYXNlZCB0byBhIGxpdHRsZSBtb3JlIHRoYW4gYHIgcm91bmQodmlvbGF0aW9uc195ZWFyJHJhdGlvWzldKWAKIC0gSW4gMjAxOCwgdGhlIG51bWJlciBvZiB2aW9sYXRpb25zIHBlciByZXN0YXVyYW50IGRlY2xpbmVkIHRvIGFwcHJveGltYXRlbHkgYHIgcm91bmQodmlvbGF0aW9uc195ZWFyJHJhdGlvWzEzXSwyKWAKCiMjIyBQZXJjZW50YWdlIG9mIHJlc3RhdXJhbnRzIHdpdGggdmlvbGF0aW9uCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQp1bmlxdWVfYnVzaW5lc3NfdmlvbGF0aW9uX3llYXIgPC0gaW5zcGVjdGlvbl9kYXRhICU+JSAKICAgIGdyb3VwX2J5KFllYXIpJT4lIAogICAgZmlsdGVyKFZpb2xhdGlvbl9Qb2ludHMgIT0gMCkgJT4lCiAgICBzdW1tYXJpc2UoY291bnRfdW5pcXVlX2J1c2luZXNzZXMgPSBuX2Rpc3RpbmN0KEJ1c2luZXNzX0lEKSkKCnVuaXF1ZV9idXNpbmVzc192aW9sYXRpb25feWVhciRyYXRpbyA8LSB1bmlxdWVfYnVzaW5lc3NfdmlvbGF0aW9uX3llYXIkY291bnRfdW5pcXVlX2J1c2luZXNzZXMvdW5pcXVlX2J1c2luZXNzX2luc3BlY3Rpb25feWVhciRjb3VudF9idXNpbmVzc2VzCgp1bmlxdWVfYnVzaW5lc3NfdmlvbGF0aW9uX3llYXIlPiUKICAgIGdncGxvdChtYXBwaW5nID0gYWVzKHkgPSByYXRpbywgeCA9IFllYXIpKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGdlb21fbGluZShncm91cCA9IDEpIApgYGAKCiAtIEFnYWluIHdlIGhhdmUgMjAxOSBoZXJlIGJlY2F1c2Ugd2UgYXJlIGNhbGN1bGF0aW5nIHBlcmNlbnRhZ2UsIG5vdCB0aGUgYWJzb2x1dGVzCiAtIFRoZSBwZXJjZW50YWdlIG9mIHJlc3RhdXJhbnRzIHZpb2xhdGluZyBpbmNyZWFzZWQgdG8gYHIgcm91bmQodW5pcXVlX2J1c2luZXNzX3Zpb2xhdGlvbl95ZWFyJHJhdGlvWzldLDIpKjEwMGAlIGluIDIwMTQgYW5kIHRoZW4gc3RhcnRlZCB0byBkZWNsaW5lIGluIDIwMTUKIC0gV2UgY2FuIHNlZSB0aGVyZSBpcyBhIHNoYXJwIGRlY2xpbmUgaW4gMjAxOSB3aGljaCBpcyBgciByb3VuZCh1bmlxdWVfYnVzaW5lc3NfdmlvbGF0aW9uX3llYXIkcmF0aW9bOV0sMikqMTAwYCUKCiMjIyBQZXJjZW50YWdlIG9mIHJlc3RhdXJhbnRzIHdpdGggbm8gdmlvbGF0aW9uCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpub25lX2NvdW50IDwtIGluc3BlY3Rpb25fZGF0YSAlPiUgCiAgZ3JvdXBfYnkoWWVhciwgQnVzaW5lc3NfSUQpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBsZW5ndGgod2hpY2goVmlvbGF0aW9uX1R5cGUgIT0gIk5PTkUiKSkpICU+JSAKICBmaWx0ZXIoY291bnQgPT0gMCkgJT4lIAogIGdyb3VwX2J5KFllYXIpICU+JSAKICBzdW1tYXJpc2Uobm9uZSA9IG4oKSkKCm5vbmVfY291bnQkcmF0aW8gPC0gbm9uZV9jb3VudCRub25lIC8gdW5pcXVlX2J1c2luZXNzX2luc3BlY3Rpb25feWVhciRjb3VudF9idXNpbmVzc2VzCgpub25lX2NvdW50ICU+JSAKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gWWVhciwgeSA9IHJhdGlvKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX2xpbmUoZ3JvdXAgPSAxKSAKYGBgCgogLSAgVGhlIHBlcmNlbnRhZ2Ugb2YgYnVzaW5lc3NlcyBpbiBLaW5nIENvdW50eSB0aGF0IGhhdmUgbm8gdmlvbGF0aW9uIGluY3JlYXNlZCBpbiAyMDE4IGZyb20gYHIgcm91bmQobm9uZV9jb3VudCRyYXRpb1sxMl0qMTAwLDIpYCUgdG8gYHIgcm91bmQobm9uZV9jb3VudCRyYXRpb1sxM10qMTAwLDIpYCUgIAogLSBUaGUgcGVyY2VudGFnZSBoYXMgZnVydGhlciBpbmNyZWFzZWQgdG8gYHIgcm91bmQobm9uZV9jb3VudCRyYXRpb1sxNF0qMTAwLDIpYCUgaW4gMjAxOSAgICAgIAogLSBIYXMgdGhpcyBwZXJjZW50YWdlIGltcHJvdmVkIGFjcm9zcyBtYWpvciA1IGNpdGllcz8KCiMjIyBQZXJjZW50YWdlIG9mIHJlc3RhdXJhbnRzIHdpdGggcmVkIHZpb2xhdGlvbnMKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CnJlZF9jb3VudF90b3RhbCA8LSBpbnNwZWN0aW9uX2RhdGEgJT4lIAogIGdyb3VwX2J5KFllYXIsIEJ1c2luZXNzX0lEKSAlPiUKICBzdW1tYXJpc2UoY291bnQgPSBsZW5ndGgod2hpY2goVmlvbGF0aW9uX1R5cGUgPT0gIlJFRCIpKSkgJT4lCiAgZmlsdGVyKGNvdW50ICE9IDApIAoKcmVkX2NvdW50IDwtIHJlZF9jb3VudF90b3RhbCAlPiUKICBncm91cF9ieShZZWFyKSAlPiUKICBzdW1tYXJpc2UocmVkID0gbigpKQoKcmVkX2NvdW50JHJhdGlvIDwtIHJlZF9jb3VudCRyZWQvdW5pcXVlX2J1c2luZXNzX2luc3BlY3Rpb25feWVhciRjb3VudF9idXNpbmVzc2VzCgpyZWRfY291bnQgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IFllYXIsIHkgPSByYXRpbykpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9saW5lKGdyb3VwID0gMSkgCgpgYGAKCiAtIFRoZSBwZXJjZW50YWdlIG9mIHJlc3RhdXJhbnQgd2l0aCByZWQgdmlvbGF0aW9ucyB3ZXJlIHJlYWxseSBoaWdoIGluIDIwMTQgYW5kIDIwMTUgd2hpY2ggd2VyZSBgciByb3VuZChyZWRfY291bnQkcmF0aW9bOV0sMikqMTAwYCUgYW5kIGByIHJvdW5kKHJlZF9jb3VudCRyYXRpb1sxMF0qMTAwLDIpYCUgcmVzcGVjdGl2ZWx5CiAtIFRoZXkgc3RhcnRlZCB0byBkZWNsaW5lIGluIDIwMTYKIC0gSGFzIHRoaXMgcGVyY2VudGFnZSBpbXByb3ZlZCBhY3Jvc3MgbWFqb3IgNSBjaXRpZXM/CgojIyMgUGVyY2VudGFnZSBvZiByZXN0YXVyYW50cyB3aXRoIGJsdWUgdmlvbGF0aW9ucwoKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KYmx1ZV9jb3VudF90b3RhbCA8LSBpbnNwZWN0aW9uX2RhdGEgJT4lIAogIGdyb3VwX2J5KFllYXIsIEJ1c2luZXNzX0lEKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbGVuZ3RoKHdoaWNoKFZpb2xhdGlvbl9UeXBlID09ICJCTFVFIikpKSAlPiUKICBmaWx0ZXIoY291bnQgIT0gMCkKCnJlZF9jb3VudF90b3RhbCA8LSByZWRfY291bnRfdG90YWwgJT4lIHNlbGVjdCgtMykgCmJsdWVfY291bnRfdG90YWwgPC0gYmx1ZV9jb3VudF90b3RhbCAlPiUgc2VsZWN0KC0zKQoKaW50ZXJzZWN0IDwtIGlubmVyX2pvaW4ocmVkX2NvdW50X3RvdGFsLCBibHVlX2NvdW50X3RvdGFsKQpibHVlX2NvdW50IDwtIGFudGlfam9pbihibHVlX2NvdW50X3RvdGFsLCBpbnRlcnNlY3QsIGJ5ID0gYygnWWVhcicsJ0J1c2luZXNzX0lEJykpCgpibHVlX2NvdW50IDwtIGJsdWVfY291bnQgJT4lCiAgICAgICAgICAgICAgZ3JvdXBfYnkoWWVhcikgJT4lCiAgICAgICAgICAgICAgc3VtbWFyaXNlKGJsdWUgPSBuKCkpCgpibHVlX2NvdW50JHJhdGlvIDwtIGJsdWVfY291bnQkYmx1ZS91bmlxdWVfYnVzaW5lc3NfaW5zcGVjdGlvbl95ZWFyJGNvdW50X2J1c2luZXNzZXMKCmJsdWVfY291bnQgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IFllYXIsIHkgPSByYXRpbykpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9saW5lKGdyb3VwID0gMSkgKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gYygnMjAwNic6JzIwMTknKSkKICAKYGBgCgotIFRoZSBwZXJjZW50YWdlIG9mIHJlc3RhdXJhbnRzIHdpdGggYmx1ZSB2aW9sYXRpb25zIGRlY2xpbmVkIHRvIGByIHJvdW5kKGJsdWVfY291bnQkcmF0aW9bMTBdLDIpKjEwMGAlIGluIDIwMTUKLSBJdCBzdGFydGVkIHRvIGluY3JlYXNlIGluIDIwMTYgYnV0IHRoZSBwZXJjZW50YWdlIGRpZmZlcmVuY2UgaXMgbm90IHZlcnkgaGlnaAoKIyMjIFBlcmNlbnRhZ2Ugb2YgcmVzdGF1cmFudHMgd2l0aCBubyB2aW9sYXRpb24gYWNyb3NzIDUgbWFqb3IgY2l0aWVzCgpgYGB7cn0KY2l0eV91bmlxdWVfYnVzaW5lc3NfaW5zcGVjdGlvbl95ZWFyIDwtIGluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JSAKICBmaWx0ZXIoQ2l0eSAlaW4lIGMoIkJFTExFVlVFIiwiS0VOVCIsIkZFREVSQUwgV0FZIiwiU0VBVFRMRSIsIlJFTlRPTiIpKSAlPiUgCiAgZ3JvdXBfYnkoWWVhciwgQ2l0eSkgJT4lIAogIHN1bW1hcmlzZShjb3VudF9idXNpbmVzc2VzID0gbl9kaXN0aW5jdChCdXNpbmVzc19JRCkpCgpjaXR5X25vbmVfY291bnQgPC0gaW5zcGVjdGlvbl9kYXRhICU+JSAKICBmaWx0ZXIoQ2l0eSAlaW4lIGMoIkJFTExFVlVFIiwiS0VOVCIsIkZFREVSQUwgV0FZIiwiU0VBVFRMRSIsIlJFTlRPTiIpKSAlPiUgCiAgZ3JvdXBfYnkoWWVhciwgQ2l0eSwgQnVzaW5lc3NfSUQpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBsZW5ndGgod2hpY2goVmlvbGF0aW9uX1R5cGUgIT0gIk5PTkUiKSkpICU+JSAKICBmaWx0ZXIoY291bnQgPT0gMCkgJT4lIAogIGdyb3VwX2J5KFllYXIsIENpdHkpICU+JSAKICBzdW1tYXJpc2Uobm9uZSA9IG4oKSkKCm1lcmdlZF9ub25lIDwtIG1lcmdlKGNpdHlfdW5pcXVlX2J1c2luZXNzX2luc3BlY3Rpb25feWVhciwgY2l0eV9ub25lX2NvdW50LCBieSA9IGMoJ1llYXInLCdDaXR5JykpCm1lcmdlZF9ub25lJHJhdGUgPC0gbWVyZ2VkX25vbmUkbm9uZS9tZXJnZWRfbm9uZSRjb3VudF9idXNpbmVzc2VzCgptZXJnZWRfbm9uZSAlPiUgCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeSA9IHJhdGUsIHggPSBZZWFyLCBncm91cCA9IENpdHkpKSArCiAgZ2VvbV9saW5lKCkgKwogIGZhY2V0X3dyYXAofkNpdHkpCmBgYAoKIC0gQWxsIDUgY2l0aWVzIGFyZSByZXNwb25kaW5nIGFyZSBpbXByb3ZlZCB3aXRoIHRoZSBuZXcgcmF0aW5nIHN5c3RlbSBpbiAyMDE3IGluIHRlcm1zIG9mIHBlcmNlbnRhZ2Ugb2Ygbm9uLXZpb2xhdGluZyByZXN0YXVyYW50cwogLSBTZWF0dGxlIHNlZW1zIHRvIGJlIGNvbnNpc3RlbnQgYWZ0ZXIgdGhhdCBhcyB3ZWxsCiAKIyMjIFBlcmNlbnRhZ2Ugb2YgcmVzdGF1cmFudHMgd2l0aCByZWQgdmlvbGF0aW9uIGFjcm9zcyA1IG1ham9yIGNpdGllcwoKYGBge3J9CmNpdHlfcmVkX2NvdW50X3RvdGFsIDwtIGluc3BlY3Rpb25fZGF0YSAlPiUgCiAgZmlsdGVyKENpdHkgJWluJSBjKCJCRUxMRVZVRSIsIktFTlQiLCJGRURFUkFMIFdBWSIsIlNFQVRUTEUiLCJSRU5UT04iKSkgJT4lIAogIGdyb3VwX2J5KFllYXIsIENpdHksIEJ1c2luZXNzX0lEKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbGVuZ3RoKHdoaWNoKFZpb2xhdGlvbl9UeXBlID09ICJSRUQiKSkpICU+JSAKICBmaWx0ZXIoY291bnQgIT0gMCkgCgpjaXR5X3JlZF9jb3VudCA8LSBjaXR5X3JlZF9jb3VudF90b3RhbCAlPiUgCiAgZ3JvdXBfYnkoWWVhciwgQ2l0eSkgJT4lIAogIHN1bW1hcmlzZShyZWQgPSBuKCkpCgptZXJnZWRfcmVkIDwtIG1lcmdlKGNpdHlfdW5pcXVlX2J1c2luZXNzX2luc3BlY3Rpb25feWVhciwgY2l0eV9yZWRfY291bnQsIGJ5ID0gYygnWWVhcicsJ0NpdHknKSkKbWVyZ2VkX3JlZCRyYXRlIDwtIG1lcmdlZF9yZWQkcmVkL21lcmdlZF9yZWQkY291bnRfYnVzaW5lc3NlcwoKCm1lcmdlZF9yZWQgJT4lIAogIGdncGxvdChtYXBwaW5nID0gYWVzKHkgPSByYXRlLCB4ID0gWWVhciwgZ3JvdXAgPSBDaXR5KSkgKwogIGdlb21fbGluZSgpICsKICBmYWNldF93cmFwKH5DaXR5KQpgYGAKCiAtIE90aGVyIHRoYW4gUmVudG9uLCB0aGVyZSB3YXMgYSBkZWNsaW5lIGluIHBlcmNlbnRhZ2Ugb2YgcmVkIHZpb2xhdGlvbiByZXN0YXVyYW50cyBmcm9tIDIwMTYgdG8gMjAxNwogLSBPbmx5IFNlYXR0bGUgc2VlbXMgdG8gYmUgZm9sbG93IHRoZSB0cmVuZCBhZnRlciB0aGF0IGFzIHdlbGwKCiMjIyBQZXJjZW50YWdlIG9mIHJlc3RhdXJhbnRzIHdpdGggYmx1ZSB2aW9sYXRpb24gYWNyb3NzIDUgbWFqb3IgY2l0aWVzCgpgYGB7cn0KY2l0eV9ibHVlX2NvdW50X3RvdGFsIDwtIGluc3BlY3Rpb25fZGF0YSAlPiUgCiAgZmlsdGVyKENpdHkgJWluJSBjKCJCRUxMRVZVRSIsIktFTlQiLCJGRURFUkFMIFdBWSIsIlNFQVRUTEUiLCJSRU5UT04iKSkgJT4lCiAgZ3JvdXBfYnkoWWVhciwgQ2l0eSwgQnVzaW5lc3NfSUQpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBsZW5ndGgod2hpY2goVmlvbGF0aW9uX1R5cGUgPT0gIkJMVUUiKSkpICU+JQogIGZpbHRlcihjb3VudCAhPSAwKQoKY2l0eV9yZWRfY291bnRfdG90YWwgPC0gY2l0eV9yZWRfY291bnRfdG90YWwgJT4lIHNlbGVjdCgtNCkgCmNpdHlfYmx1ZV9jb3VudF90b3RhbCA8LSBjaXR5X2JsdWVfY291bnRfdG90YWwgJT4lIHNlbGVjdCgtNCkKaW50ZXJzZWN0IDwtIGlubmVyX2pvaW4oY2l0eV9yZWRfY291bnRfdG90YWwsIGNpdHlfYmx1ZV9jb3VudF90b3RhbCkKY2l0eV9ibHVlX2NvdW50IDwtIGFudGlfam9pbihjaXR5X2JsdWVfY291bnRfdG90YWwsIGludGVyc2VjdCwgYnkgPSBjKCdZZWFyJywnQ2l0eScsJ0J1c2luZXNzX0lEJykpCmNpdHlfYmx1ZV9jb3VudCA8LSBjaXR5X2JsdWVfY291bnQgJT4lCiAgICAgICAgICAgICAgZ3JvdXBfYnkoWWVhciwgQ2l0eSkgJT4lCiAgICAgICAgICAgICAgc3VtbWFyaXNlKGJsdWUgPSBuKCkpCgptZXJnZWRfYmx1ZSA8LSBtZXJnZShjaXR5X3VuaXF1ZV9idXNpbmVzc19pbnNwZWN0aW9uX3llYXIsIGNpdHlfYmx1ZV9jb3VudCwgYnkgPSBjKCdZZWFyJywnQ2l0eScpKQptZXJnZWRfYmx1ZSRyYXRlIDwtIG1lcmdlZF9ibHVlJGJsdWUvbWVyZ2VkX2JsdWUkY291bnRfYnVzaW5lc3NlcwoKCm1lcmdlZF9ibHVlICU+JSAKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh5ID0gcmF0ZSwgeCA9IFllYXIsIGdyb3VwID0gQ2l0eSkpICsKICBnZW9tX2xpbmUoKSArCiAgZmFjZXRfd3JhcCh+Q2l0eSkKYGBgCgogLSBUaGVyZSBpcyBubyBtYWpvciBpbXBhY3Qgb24gYmx1ZSB2aW9sYXRpb24gcmVzdGF1cmFudHMgYWNyb3NzIDUgbWFqb3IgY2l0aWVzIGZyb20gMjAxNiB0byAyMDE3CiAtIEZlZGVyYWwgd2F5IHNlZW1zIHRvIGJlIHBlcmZvcm1pbmcgdGhlIHdvcnN0CgojIyMgTW9udGhseSBwYXR0ZXJuIG9mIHJlZCB2aW9sYXRpb25zCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQppbnNwZWN0aW9uX2RhdGEgJT4lCiAgZmlsdGVyKFZpb2xhdGlvbl9Qb2ludHMgIT0gMCkgJT4lCiAgZ3JvdXBfYnkoWWVhciwgTW9udGgpICU+JQogIGZpbHRlcihZZWFyICE9ICcyMDE5JykgJT4lCiAgc3VtbWFyaXNlKGNvdW50ID0gbGVuZ3RoKHdoaWNoKFZpb2xhdGlvbl9UeXBlID09ICJSRUQiKSkpICU+JQogIGdncGxvdChtYXBwaW5nID0gYWVzKHkgPSBjb3VudCwgeCA9IE1vbnRoLCBncm91cCA9IDEpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBmYWNldF93cmFwKH5ZZWFyKSAKYGBgCgogLSBJdCBhcHBlYXJzIHRoYXQgcmVkIHZpb2xhdGlvbnMgaW5jcmVhc2UgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgeWVhciwgY29tZXMgZG93biBpbiBzdW1tZXIgYW5kIHRoZW4gaW5jcmVhc2UgZHVyaW5nIHdpbnRlciBhZ2FpbgogLSBGb3Igc29tZSByZWFzb24sIERlY2VtYmVyIDIwMDggaGFkIHZlcnkgZmV3IHJlZCB2aW9sYXRpb25zCiAtIFRoaXMgaXMgYSBwYXR0ZXJuIHRvIGJlIGFuYWx5emVkIGluIGZ1dHVyZSBhcyBob3cgZG9lcyB0aGUgc2Vhc29ucyBhZmZlY3QgdmlvbGF0aW9ucz8KCiMjIyBQYXR0ZXJuIG9mIHZpb2xhdGlvbiBudW1iZXJzIGV2ZXJ5IG1vbnRoCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpjb3VudF92aW9sYXRpb25fbnVtYmVyIDwtIGluc3BlY3Rpb25fZGF0YSAlPiUgCiAgZ3JvdXBfYnkoTW9udGgsIFZpb2xhdGlvbl9OdW1iZXIpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpCgpjb3VudF92aW9sYXRpb25fbnVtYmVyW29yZGVyKGNvdW50X3Zpb2xhdGlvbl9udW1iZXIkTW9udGgsLWNvdW50X3Zpb2xhdGlvbl9udW1iZXIkY291bnQpLF0gJT4lIAogIGZpbHRlcihWaW9sYXRpb25fTnVtYmVyICE9ICdOT05FJykgJT4lIAogIGdyb3VwX2J5KE1vbnRoKSAlPiUgCiAgdG9wX24obj0zKSAlPiUKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4PU1vbnRoLCB5PWNvdW50LCBmaWxsID0gVmlvbGF0aW9uX051bWJlcikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgY29vcmRfZmxpcCgpCiAgCmBgYAoKIC0gVGhlc2UgYXJlIHRoZSB0b3AgMyB2aW9sYXRpb24gdHlwZXMgb2N1cnJpbmcgZXZlcnkgbW9udGgKIC0gMjAwIChGb29kIHdvcmtlciBjYXJkcyBub3QgY3VycmVudCksIDYwMCAoQWRlcXVhdGUgaGFuZHdhc2hpbmcpIGFuZCAyMTEwIChQcm9wZXIgY29sZCBob2xkaW5nIHRlbXBlYXJhdHVyZSkgYXJlIHJlZCB2aW9sYXRpb25zCiAtIDM0MDAgKFdpcGluZyBjbG90aGVzIHByb3Blcmx5IHVzZWQpIGlzIGEgYmx1ZSB2aW9sYXRpb24KIC0gVmlvbGF0aW9uIG51bWJlciAwMjAwICBpcyBtb3JlIGNvbW1vbiBpbiBKYW51YXJ5IGFuZCBGZWJydWFyeQoKIyMjIE1lZGlhbiBvZiBpbnNwZWN0aW9uIHNjb3JlcyBmb3IgdmlvbGF0aW5nIGJ1c2luZXNzZXMKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9Cmluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JQogIGZpbHRlcihJbnNwZWN0aW9uX1Njb3JlICE9IDApICU+JQogIGdyb3VwX2J5KFllYXIpICU+JQogIHN1bW1hcmlzZShzY29yZSA9IG1lZGlhbihJbnNwZWN0aW9uX1Njb3JlKSkgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeSA9IHNjb3JlLCB4ID0gWWVhciwgZ3JvdXAgPSAxKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9saW5lKCkKCmBgYAoKIC0gMjAxNCBmb29kIGlsbG5lc3Mgb3V0YnJlYWsgaGFzIHNvbWV0aGluZyB0byBkbyB3aXRoIHRoZSBpbmNyZWFzZSBvZiBpbnNwZWN0aW9uIHNjb3JlPyAgCiAtIFRoZSBtZWRpYW4gb2YgaW5zcGVjdGlvbiBzY29yZXMgZGVjbGluZSBkcmFzdGljYWxseSBmcm9tIDIwMTYgdG8gMjAxNwogLSBUaGlzIG1pZ2h0IGJlIHRoZSBpbXBhY3Qgb2YgdGhlIG5ldyByYXRpbmcgc3lzdGVtIGludHJvZHVjZWQgaW4gMjAxNyAgCiAtIElzIHRoZSBzYW1lIHBhdHRlcm4gYWNyb3NzIHRoZSA1IG1ham9yIGNpdGllcz8KCiMjIyBNZWRpYW4gb2YgaW5zcGVjdGlvbiBzY29yZXMgZm9yIHZpb2xhdGluZyBidXNpbmVzc2VzIGFjcm9zcyA1IG1ham9yIGNpdGllcwoKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lCiAgZmlsdGVyKEluc3BlY3Rpb25fU2NvcmUgIT0gMCkgJT4lCiAgZmlsdGVyKENpdHkgJWluJSBjKCJTRUFUVExFIiwiQkVMTEVWVUUiLCJSRU5UT04iLCJLRU5UIiwiRkVERVJBTCBXQVkiKSkgJT4lIAogIGdyb3VwX2J5KFllYXIsIENpdHkpICU+JQogIHN1bW1hcmlzZShzY29yZSA9IG1lZGlhbihJbnNwZWN0aW9uX1Njb3JlKSkgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeSA9IHNjb3JlLCB4ID0gWWVhciwgZ3JvdXAgPSBDaXR5KSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9saW5lKCkgKwogIGZhY2V0X3dyYXAofkNpdHkpCgpgYGAKCiAtIEJlbGxldnVlIGRpZCBub3QgaGF2ZSBhIGRlY2xpbmUgaW4gbWVkaWFuIGluc3BlY3Rpb24gc2NvcmUgc2luY2UgMjAwOAogLSBTZWF0dGxlIGlzIHRoZSBvbmx5IGNpdHkgd2hlcmUgbWVkaWFuIGluc3BlY3Rpb24gc2NvcmUgZGVjbGluZWQgaW4gMjAxNyAgCiAtIE1lZGlhbiBpbnNwZWN0aW9uIHNjb3JlIGluIFJlbnRvbiBkZWNsaW5lZCBpbiAyMDE4CiAKIyMjIEluc3BlY3Rpb24gc2NvcmVzIGFjcm9zcyBTZWF0aW5nIHR5cGVzCiAKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lIAogIGdncGxvdChhZXMoeCA9IFNlYXRpbmcsIHkgPSBJbnNwZWN0aW9uX1Njb3JlKSkgKwogIGdlb21fYm94cGxvdCgpICsKICB5bGltKDAsNTApCmBgYAogCiAtIFRoZXJlIGFyZSBkaWZmZXJlbmNlcyBpbiB0aGUgaW50ZXIgcXVhcnRpbGUgcmFuZ2UgZm9yIGluc3BlY3Rpb24gc2NvcmVzIGZvciB2YXJpb3VzIHNlYXRpbmcgdHlwZXMgCiAKIyMjIEluc3BlY3Rpb24gc2NvcmVzIGFjcm9zcyBSaXNrIENhdGVnb3JpZXMKIApgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfSAKaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lIAogIGdncGxvdChhZXMoeCA9IFJpc2tfQ2F0ZWdvcnksIHkgPSBJbnNwZWN0aW9uX1Njb3JlKSkgKwogIGdlb21fYm94cGxvdCgpICsKICB5bGltKDAsNTApCgppbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gSW5zcGVjdGlvbl9TY29yZSwgZmlsbCA9IFJpc2tfQ2F0ZWdvcnkpKSArCiAgZ2VvbV9kZW5zaXR5KCkgKwogIHhsaW0oMCw1MCkKYGBgCgogLSBSZXN0YXVyYW50cyB3aXRoIFJpc2sgQ2F0ZWdvcnkgSUlJIGhhdmUgaGlnaGVyIGludGVycXVhcnRpbGUgcmFuZ2UgZm9yIGluc3BlY3Rpb24gc2NvcmVzCiAKIyMjIEluc3BlY3Rpb24gc2NvcmVzIGFjcm9zcyBDaXRpZXMKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CgppbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUgCiAgZmlsdGVyKENpdHkgJWluJSBjKCJTRUFUVExFIiwiQkVMTEVWVUUiLCJSRU5UT04iLCJGRURFUkFMIFdBWSIsIktFTlQiKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IENpdHksIHkgPSBJbnNwZWN0aW9uX1Njb3JlKSkgKwogIGdlb21fYm94cGxvdCgpICsKICB5bGltKDAsNTApCgppbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUgCiAgZmlsdGVyKENpdHkgJWluJSBjKCJTRUFUVExFIiwiQkVMTEVWVUUiLCJSRU5UT04iLCJGRURFUkFMIFdBWSIsIktFTlQiKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IEluc3BlY3Rpb25fU2NvcmUsIGZpbGwgPSBDaXR5KSkgKwogIGdlb21fZGVuc2l0eSgpICsKICB4bGltKDAsNTApCgpgYGAKCiAtIEJlbGxldnVlLCBTZWF0dGxlIGFuZCBGZWRlcmFsIFdheSBoYXZlIHdpZGVyIGludGVycXVhcnRpbGUgcmFuZ2UgZm9yIGluc3BlY3Rpb24gc2NvcmUKIC0gSG93IGRvZXMgdGhpcyB2YXJ5IGFjcm9zcyB0aGUgeWVhcnM/CgogCisgX19GaW5kaW5nc19fCiAtIEluIHRoZSBuZXcgc3lzdGVtIGludHJvZHVjZWQgaW4gMjAxNywgbnVtYmVyIG9mIGluc3BlY3Rpb25zIGFyZSBpbmNyZWFzaW5nIGF0IGEgaGlnaGVyIHJhdGUgYXMgY29tcGFyZWQgdG8gaW5jcmVhc2UgaW4gdGhlIG51bWJlciBvZiByZXN0YXVyYW50cyAgCiAtIFBlcmNlbnRhZ2Ugb2YgcmVzdGF1cmFudHMgcmVxdWlyaW5nIHJldHVybiBpbnNwZWN0aW9uIHdlcmUgcmVhbGx5IGhpZ2ggaW4gMjAxNCBhbmQgMjAxNSBhbmQgc3RhcnRlZCB0byBkZWNsaW5lIGluIDIwMTYKIC0gSW4gMjAxNCwgdGhlcmUgd2VyZSBhIGhpZ2ggbnVtYmVyIG9mIHZpb2xhdGlvbnMgZXZlbiB0aG91Z2ggdGhlIGluY3JlYXNlIGluIG51bWJlciBvZiByZXN0YXVyYW50cyBncmV3IGF0IHRoZSByZWd1bGFyIHJhdGUgd2hpY2ggaW1wbGllcyB0aGVyZSB3ZXJlIG1vcmUgdmlvbGF0aW9ucyBwZXIgcmVzdGF1cmFudCBpbiAyMDE0CiAtIFdpdGggdGhlIGVuZm9yY2VtZW50IG9mIG5ldyByYXRpbmcgc3lzdGVtLCB0aGUgbnVtYmVyIG9mIHJlc3RhdXJhbnRzIHdpdGggbm8gdmlvbGF0aW9ucyBpbmNyZWFzZWQgbXVjaCBmYXN0ZXIKIC0gVGhlcmUgd2FzIGEgaHVnZSBpbmNyZWFzZSBpbiByZWQgdmlvbGF0aW9ucyBpbiAyMDE0IHdoaWNoIG9ubHkgc3RhcnRlZCB0byByZWR1Y2Ugc2luY2UgMjAxNwogLSBBZnRlciB0aGUgaW50cm9kdWN0aW9uIG9mIHRoZSBuZXcgcmF0aW5nIHN5c3RlbSwgbnVtYmVyIG9mIHJlc3RhdXJhbnRzIHdpdGggMCBjcml0aWNhbCB2aW9sYXRpb25zIGluY3JlYXNlZCBmcm9tIDU1JSBpbiAyMDE2IHRvIDU3JSBpbiAyMDE3LiBJdCBmdXJ0aGVyIGluY3JlYXNlZCB0byA2MSUgaW4gMjAxOC4KIC0gTnVtYmVyIG9mIHJlZCB2aW9sYXRpb25zIGZvbGxvdyBhIHBhdHRlcm4gdGhyb3VnaG91dCB0aGUgeWVhci4gU3ByaW5nIGhhcyB0aGUgbWF4aW11bSBudW1iZXIgb2YgcmVkIHZpb2xhdGlvbnMgZm9sbG93ZWQgYnkgd2ludGVyCiAtIFRoZSBtb3N0IGNvbW1vbiB0eXBlcyBvZiB2aW9sYXRpb25zIG9jY3VycmluZyBhcmUgMjAwLDYwMCwyMTEwIChSZWQpIGFuZCAzNDAwIChCbHVlKQogLSBJbnNwZWN0aW9uIFNjb3JlIHNob290IHVwIHJlYWxseSBoaWdoIGluIDIwMTQgYW5kIHN0YXJ0ZWQgdG8gZGVjbGluZSBzaWduaWZpY2FudGx5IGFmdGVyIDIwMTcgc2luY2UgdGhlIGludHJvZHVjdGlvbiBvZiB0aGUgbmV3IHJhdGluZyBzeXN0ZW0KIC0gVGhlIG1lZGlhbiBpbnNwZWN0aW9uIHNjb3JlIG9mIDUgbWFqb3IgY2l0aWVzIGlzIGNsb3NlciB0byB6ZXJvLCBkb2VzIHRoaXMgcGF0dGVybiBjaGFuZ2UgYWZ0ZXIgdGhlIGludHJvZHVjdGlvbiBvZiB0aGUgbmV3IHJhdGluZyBzeXN0ZW0/CiAtIE1lZGlhbiBJbnNwZWN0aW9uIFNjb3JlIG5ldmVyIGRlY2xpbmVkIGluIEJlbGxldnVlCiAtIFNlYXR0bGUgaXMgdGhlIG9ubHkgY2l0eSB3aGVyZSBtZWRpYW4gaW5zcGVjdGlvbiBzY29yZSBkZWNsaW5lZCBpbiAyMDE3CiAKIyBUZXN0aW5nIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZQoKIyMgVGhlIHBlcmNlbnRhZ2Ugb2YgcmVzdGF1cmFudHMgd2l0aCBubyB2aW9sYXRpb25zL3JlZCB2aW9sYXRpb25zL2JsdWUgdmlvbGF0aW9ucyBoYXZlIGNoYW5nZWQgc2luY2UgdGhlIGludHJvZHVjdGlvbiBvZiBuZXcgcmF0aW5nIHN5c3RlbSBpbiAyMDE3CgpXZSBhcmUgZ29pbmcgdG8gcGVyZm9ybSBhIGNoaSBzcXVhcmUgdGVzdCB3aGVyZSB3ZSB3aWxsIGNvbXBhcmUgdGhlIDIwMTcgZGF0YSAocHJvcG9ydGlvbiBvZiByZXN0YXVyYW50cyB3aXRoIG5vbmUvcmVkL2JsdWUgdmlvbGF0aW9ucykgYWdhaW5zdCB0aGUgcHJvcG9ydGlvbiBvZiByZXN0YXVyYW50cyB3aXRoIG5vbmUvcmVkL2JsdWUgdmlvbGF0aW9ucyB3aGljaCBoYXBwZW5lZCBpbiAyMDE2ICAgCk5vdGU6IFJlc3RhdXJhbnRzIHdoaWNoIGhhdmUgYm90aCByZWQgYW5kIGJsdWUgdmlvbGF0aW9ucywgaGF2ZSBiZWVuIGNhdGVnb3JpemVkIHVuZGVyIHJlc3RhdXJhbnRzIHdpdGggcmVkIHZpb2xhdGlvbnMKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0Kbm9uZV9jb3VudCA8LSBub25lX2NvdW50ICU+JSBzZWxlY3QoMSwyKQpyZWRfY291bnQgPC0gcmVkX2NvdW50ICU+JSBzZWxlY3QoMSwyKQpibHVlX2NvdW50IDwtIGJsdWVfY291bnQgJT4lIHNlbGVjdCgxLDIpCgptZXJnZWRfdmlvbGF0aW9ucyA8LSBtZXJnZSh1bmlxdWVfYnVzaW5lc3NfaW5zcGVjdGlvbl95ZWFyLG5vbmVfY291bnQsIGJ5ID0gYygnWWVhcicpLCBhbGwueCA9IFRSVUUpCm1lcmdlZF92aW9sYXRpb25zIDwtIG1lcmdlKG1lcmdlZF92aW9sYXRpb25zLCByZWRfY291bnQsIGJ5ID0gYygnWWVhcicpLCBhbGwueCA9IFRSVUUpCm1lcmdlZF92aW9sYXRpb25zIDwtIG1lcmdlKG1lcmdlZF92aW9sYXRpb25zLCBibHVlX2NvdW50LCBieSA9IGMoJ1llYXInKSwgYWxsLnggPSBUUlVFKQptZXJnZWRfdmlvbGF0aW9ucyA8LSBtZXJnZWRfdmlvbGF0aW9ucyAlPiUgZ2F0aGVyKHR5cGUsIGNvdW50LCBub25lOmJsdWUpCm1lcmdlZF92aW9sYXRpb25zJHJhdGUgPC0gbWVyZ2VkX3Zpb2xhdGlvbnMkY291bnQvbWVyZ2VkX3Zpb2xhdGlvbnMkY291bnRfYnVzaW5lc3NlcwptZXJnZWRfdmlvbGF0aW9ucyRsYWJlbCA8LSBwYXN0ZTAoc3ByaW50ZigiJS4wZiIsIG1lcmdlZF92aW9sYXRpb25zJHJhdGUqMTAwKSwgIiUiKQoKIyBTZXR0aW5nIHRoZSBwcm9iYWJpbGl0ZXMgZm9yIDIwMTYKZXhwX3Byb2IgPC0gYygobWVyZ2VkX3Zpb2xhdGlvbnMgJT4lIGZpbHRlcihZZWFyID09ICIyMDE2IiAmIHR5cGUgPT0gIm5vbmUiKSkkcmF0ZSwKICAgICAgICAgICAgIChtZXJnZWRfdmlvbGF0aW9ucyAlPiUgZmlsdGVyKFllYXIgPT0gIjIwMTYiICYgdHlwZSA9PSAicmVkIikpJHJhdGUsCiAgICAgICAgICAgICAobWVyZ2VkX3Zpb2xhdGlvbnMgJT4lIGZpbHRlcihZZWFyID09ICIyMDE2IiAmIHR5cGUgPT0gImJsdWUiKSkkcmF0ZSkKCnRlc3RfZGF0YSA8LSBjKChtZXJnZWRfdmlvbGF0aW9ucyAlPiUgZmlsdGVyKFllYXIgPT0gIjIwMTciICYgdHlwZSA9PSAibm9uZSIpKSRjb3VudCwKICAgICAgICAgICAgIChtZXJnZWRfdmlvbGF0aW9ucyAlPiUgZmlsdGVyKFllYXIgPT0gIjIwMTciICYgdHlwZSA9PSAicmVkIikpJGNvdW50LAogICAgICAgICAgICAgKG1lcmdlZF92aW9sYXRpb25zICU+JSBmaWx0ZXIoWWVhciA9PSAiMjAxNyIgJiB0eXBlID09ICJibHVlIikpJGNvdW50KQoKIyBUZXN0aW5nIHRoZSBkYXRhIG9uIHRoZSBjb3VudCBvZiBlYWNoCmNoaXNxLnRlc3QodGVzdF9kYXRhLCBleHBfcHJvYikgCmBgYAoKIC0gRnJvbSB0aGlzIHRlc3QsIHdlIGNhbiBjb25jbHVkZSB3aXRoIDgwJSBjb25maWRlbmNlIHRoYXQgdGhlcmUgaXMgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gcHJvcG9ydGlvbnMgb2YgYnVzaW5lc3NlcyBoYXZpbmcgbm9uZSwgcmVkIGFuZCBibHVlIHZpb2xhdGlvbnMgaW4gMjAxNyBhcyBjb21wYXJlZCB0byAyMDE2LgoKYGBge3J9CgptZXJnZWRfdmlvbGF0aW9ucyAlPiUKICAgICAgICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gWWVhciwgeSA9IHJhdGUsIGZpbGwgPSBmYWN0b3IodHlwZSwgbGV2ZWxzID0gYygnYmx1ZScsJ3JlZCcsJ25vbmUnKSkpKSArCiAgICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjaygpLCBzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAwLjcpICsKICAgICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbGFiZWwpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSwgc2l6ZSA9IDMsIGNvbG9yID0gJ2JsYWNrJykgKwogICAgICAgIGNvb3JkX2ZsaXAoKSArCiAgICAgICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygnc3RlZWxibHVlNCcsJ3JlZDQnLCdzbm93NCcpLCBuYW1lID0gIlZpb2xhdGlvbiBUeXBlOiIsIGxhYmVscyA9IGMoIkJsdWUiLCJSZWQiLCJOb25lIikpICsKICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnYm90dG9tJywgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLCBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJibGFjayIpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC44LCJsaW5lIiksbGVnZW5kLm1hcmdpbj1tYXJnaW4oMCwwLDAsMCksbGVnZW5kLmJveC5tYXJnaW49bWFyZ2luKC0zLC0zLC0zLC0zKSkgKwogICAgICAgIGxhYnModGl0bGUgPSAiTmV3IHJhdGluZyBzeXN0ZW0gaXMgbGVhZGluZyB0byBoZWFsdGhpZXIgcmVzdGF1cmFudHMiLCB5ID0gIiIpICsKICAgICAgICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChyZXZlcnNlID0gVFJVRSkpCgpnZ3NhdmUoJ05vX1Zpb2xhdGlvbnMucG5nJykKYGBgCgogLSBGb3IgdGhlIHllYXJzIDIwMDcsIDIwMDggYW5kIDIwMTAsIHRoZSBwZXJjZW50YWdlIGlzIG5vdCB0b3RhbGxpbmcgdG8gMTAwJSBiZWNhdXNlIG9mIHJvdW5kaW5nIG9mZiwgZm9yIHRoZSBleGFjdCBwZXJjZW50YWdlcywgcGxlYXNlIHJlZmVyIHRvIHRoZSB0YWJsZSBiZWxvdzoKIApgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpyYXRlX3RhYmxlIDwtIG1lcmdlZF92aW9sYXRpb25zICU+JSBzZWxlY3QoYygxLDMsNSkpCnJhdGVfdGFibGUgPC0gcmVzaGFwZShyYXRlX3RhYmxlLCBpZHZhciA9ICJZZWFyIiwgdGltZXZhciA9ICJ0eXBlIiwgZGlyZWN0aW9uID0gIndpZGUiKQpyYXRlX3RhYmxlJHJhdGUubm9uZSA8LSByYXRlX3RhYmxlJHJhdGUubm9uZSAqIDEwMApyYXRlX3RhYmxlJHJhdGUucmVkIDwtIHJhdGVfdGFibGUkcmF0ZS5yZWQgKiAxMDAKcmF0ZV90YWJsZSRyYXRlLmJsdWUgPC0gcmF0ZV90YWJsZSRyYXRlLmJsdWUgKiAxMDAKcmF0ZV90YWJsZSR0b3RhbCA8LSByYXRlX3RhYmxlJHJhdGUubm9uZSArIHJhdGVfdGFibGUkcmF0ZS5yZWQgKyByYXRlX3RhYmxlJHJhdGUuYmx1ZQoKcmF0ZV90YWJsZSAlPiUgCiAgbWFwX2RmKHJldikgJT4lIAogIGthYmxlKCkgJT4lIAogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRikKYGBgCgoKIyMgVGhlIHBlcmNlbnRhZ2Ugb2YgcmVzdGF1cmFudHMgd2l0aCBubyB2aW9sYXRpb25zL3JlZCB2aW9sYXRpb25zL2JsdWUgdmlvbGF0aW9ucyBoYXZlIGNoYW5nZWQgc2luY2UgdGhlIGludHJvZHVjdGlvbiBvZiBuZXcgcmF0aW5nIHN5c3RlbSBpbiAyMDE3IGFjcm9zcyA1IG1ham9yIGNpdGllcwoKVG8gdGVzdCB0aGF0LCB3ZSB3aWxsIHBlcmZvcm0gYSBzaW1pbGFyIGNoaS1zcXVhcmUgdGVzdCBmb3IgU2VhdHRsZSwgQmVsbGV2dWUsIEZlZGVyYWwgV2F5LCBLZW50LCBSZWRtb25kIGluZGl2aWR1YWxseQoKU0VBVFRMRQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQoKZXhwX3Byb2Jfc2VhdHRsZSA8LSBjKChtZXJnZWRfbm9uZSAlPiUgZmlsdGVyKFllYXIgPT0gIjIwMTYiICYgQ2l0eSA9PSAiU0VBVFRMRSIpKSRyYXRlLAoobWVyZ2VkX3JlZCAlPiUgZmlsdGVyKFllYXIgPT0gIjIwMTYiICYgQ2l0eSA9PSAiU0VBVFRMRSIpKSRyYXRlLAoobWVyZ2VkX2JsdWUgJT4lIGZpbHRlcihZZWFyID09ICIyMDE2IiAmIENpdHkgPT0gIlNFQVRUTEUiKSkkcmF0ZSkKCgp0ZXN0X2RhdGFfc2VhdHRsZSA8LSBjKChtZXJnZWRfbm9uZSAlPiUgZmlsdGVyKFllYXIgPT0gIjIwMTciICYgQ2l0eSA9PSAiU0VBVFRMRSIpKSRub25lLAogICAgICAgICAgICAgKG1lcmdlZF9yZWQgJT4lIGZpbHRlcihZZWFyID09ICIyMDE3IiAmIENpdHkgPT0gIlNFQVRUTEUiKSkkcmVkLAogICAgICAgICAgICAgKG1lcmdlZF9ibHVlICU+JSBmaWx0ZXIoWWVhciA9PSAiMjAxNyIgJiBDaXR5ID09ICJTRUFUVExFIikpJGJsdWUpCgpjaGlzcS50ZXN0KHRlc3RfZGF0YV9zZWF0dGxlLCBleHBfcHJvYl9zZWF0dGxlKSAKYGBgIAoKQkVMTEVWVUUKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KCmV4cF9wcm9iX2JlbGwgPC0gYygobWVyZ2VkX25vbmUgJT4lIGZpbHRlcihZZWFyID09ICIyMDE2IiAmIENpdHkgPT0gIkJFTExFVlVFIikpJHJhdGUsCihtZXJnZWRfcmVkICU+JSBmaWx0ZXIoWWVhciA9PSAiMjAxNiIgJiBDaXR5ID09ICJCRUxMRVZVRSIpKSRyYXRlLAoobWVyZ2VkX2JsdWUgJT4lIGZpbHRlcihZZWFyID09ICIyMDE2IiAmIENpdHkgPT0gIkJFTExFVlVFIikpJHJhdGUpCgoKdGVzdF9kYXRhX2JlbGwgPC0gYygobWVyZ2VkX25vbmUgJT4lIGZpbHRlcihZZWFyID09ICIyMDE3IiAmIENpdHkgPT0gIkJFTExFVlVFIikpJG5vbmUsCiAgICAgICAgICAgICAobWVyZ2VkX3JlZCAlPiUgZmlsdGVyKFllYXIgPT0gIjIwMTciICYgQ2l0eSA9PSAiQkVMTEVWVUUiKSkkcmVkLAogICAgICAgICAgICAgKG1lcmdlZF9ibHVlICU+JSBmaWx0ZXIoWWVhciA9PSAiMjAxNyIgJiBDaXR5ID09ICJCRUxMRVZVRSIpKSRibHVlKQoKY2hpc3EudGVzdCh0ZXN0X2RhdGFfYmVsbCwgZXhwX3Byb2JfYmVsbCkgCmBgYAoKRkVERVJBTCBXQVkKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KCmV4cF9wcm9iX2ZlZCA8LSBjKChtZXJnZWRfbm9uZSAlPiUgZmlsdGVyKFllYXIgPT0gIjIwMTYiICYgQ2l0eSA9PSAiRkVERVJBTCBXQVkiKSkkcmF0ZSwKKG1lcmdlZF9yZWQgJT4lIGZpbHRlcihZZWFyID09ICIyMDE2IiAmIENpdHkgPT0gIkZFREVSQUwgV0FZIikpJHJhdGUsCihtZXJnZWRfYmx1ZSAlPiUgZmlsdGVyKFllYXIgPT0gIjIwMTYiICYgQ2l0eSA9PSAiRkVERVJBTCBXQVkiKSkkcmF0ZSkKCgp0ZXN0X2RhdGFfZmVkIDwtIGMoKG1lcmdlZF9ub25lICU+JSBmaWx0ZXIoWWVhciA9PSAiMjAxNyIgJiBDaXR5ID09ICJGRURFUkFMIFdBWSIpKSRub25lLAogICAgICAgICAgICAgKG1lcmdlZF9yZWQgJT4lIGZpbHRlcihZZWFyID09ICIyMDE3IiAmIENpdHkgPT0gIkZFREVSQUwgV0FZIikpJHJlZCwKICAgICAgICAgICAgIChtZXJnZWRfYmx1ZSAlPiUgZmlsdGVyKFllYXIgPT0gIjIwMTciICYgQ2l0eSA9PSAiRkVERVJBTCBXQVkiKSkkYmx1ZSkKCmNoaXNxLnRlc3QodGVzdF9kYXRhX2ZlZCwgZXhwX3Byb2JfZmVkKSAKYGBgCgpLRU5UCmBgYHtyIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CgpleHBfcHJvYl9rZW50IDwtIGMoKG1lcmdlZF9ub25lICU+JSBmaWx0ZXIoWWVhciA9PSAiMjAxNiIgJiBDaXR5ID09ICJLRU5UIikpJHJhdGUsCihtZXJnZWRfcmVkICU+JSBmaWx0ZXIoWWVhciA9PSAiMjAxNiIgJiBDaXR5ID09ICJLRU5UIikpJHJhdGUsCihtZXJnZWRfYmx1ZSAlPiUgZmlsdGVyKFllYXIgPT0gIjIwMTYiICYgQ2l0eSA9PSAiS0VOVCIpKSRyYXRlKQoKCnRlc3RfZGF0YV9rZW50IDwtIGMoKG1lcmdlZF9ub25lICU+JSBmaWx0ZXIoWWVhciA9PSAiMjAxNyIgJiBDaXR5ID09ICJLRU5UIikpJG5vbmUsCiAgICAgICAgICAgICAobWVyZ2VkX3JlZCAlPiUgZmlsdGVyKFllYXIgPT0gIjIwMTciICYgQ2l0eSA9PSAiS0VOVCIpKSRyZWQsCiAgICAgICAgICAgICAobWVyZ2VkX2JsdWUgJT4lIGZpbHRlcihZZWFyID09ICIyMDE3IiAmIENpdHkgPT0gIktFTlQiKSkkYmx1ZSkKCmNoaXNxLnRlc3QodGVzdF9kYXRhX2tlbnQsIGV4cF9wcm9iX2tlbnQpIApgYGAKClJFTlRPTgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQoKZXhwX3Byb2JfcmVudG9uIDwtIGMoKG1lcmdlZF9ub25lICU+JSBmaWx0ZXIoWWVhciA9PSAiMjAxNiIgJiBDaXR5ID09ICJSRU5UT04iKSkkcmF0ZSwKKG1lcmdlZF9yZWQgJT4lIGZpbHRlcihZZWFyID09ICIyMDE2IiAmIENpdHkgPT0gIlJFTlRPTiIpKSRyYXRlLAoobWVyZ2VkX2JsdWUgJT4lIGZpbHRlcihZZWFyID09ICIyMDE2IiAmIENpdHkgPT0gIlJFTlRPTiIpKSRyYXRlKQoKCnRlc3RfZGF0YV9yZW50b24gPC0gYygobWVyZ2VkX25vbmUgJT4lIGZpbHRlcihZZWFyID09ICIyMDE3IiAmIENpdHkgPT0gIlJFTlRPTiIpKSRub25lLAogICAgICAgICAgICAgKG1lcmdlZF9yZWQgJT4lIGZpbHRlcihZZWFyID09ICIyMDE3IiAmIENpdHkgPT0gIlJFTlRPTiIpKSRyZWQsCiAgICAgICAgICAgICAobWVyZ2VkX2JsdWUgJT4lIGZpbHRlcihZZWFyID09ICIyMDE3IiAmIENpdHkgPT0gIlJFTlRPTiIpKSRibHVlKQoKY2hpc3EudGVzdChleHBfcHJvYl9yZW50b24sIGV4cF9wcm9iX3JlbnRvbikgCmBgYApGcm9tIHRoZXNlIHRlc3RzLCB3ZSBjYW4gY29uY2x1ZGUgd2l0aCA4MCUgY29uZmlkZW5jZSB0aGF0IHRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIHByb3BvcnRpb25zIG9mIHJlc3RhdXJhbnRzIGhhdmluZyBub25lLCByZWQgYW5kIGJsdWUgdmlvbGF0aW9ucyBpbiAyMDE3IGFzIGNvbXBhcmVkIHRvIDIwMTYgZm9yIGFsbCBtYWpvciA1IGNpdGllcyAtIFNlYXR0bGUsIEJlbGxldnVlLCBGZWRlcmFsIFdheSwgS2VudCBhbmQgUmVkbW9uZC4gCgoKYGBge3J9CnN1YnRpdGxlID0gcGFzdGUwKCJJbiBTZWF0dGxlLCByZXN0YXVyYW50cyB3aXRoIG5vIHZpb2xhdGlvbnMgaW5jcmVhc2VkIHRvICIscm91bmQobWVyZ2VkX25vbmVbNjAsNV0qMTAwKSwgIiUsICIscm91bmQobWVyZ2VkX25vbmVbNjUsNV0qMTAwKSwgIiUgYW5kICIscm91bmQobWVyZ2VkX25vbmVbNzAsNV0qMTAwKSwgIiUgaW4gMjAxNywgMjAxOCBhbmQgMjAxOSwgcmVzcGVjdGl2ZWx5IikgCgptZXJnZWRfbm9uZSAlPiUgCiAgZmlsdGVyKENpdHkgJWluJSBjKCJCRUxMRVZVRSIsIktFTlQiLCJGRURFUkFMIFdBWSIsIlNFQVRUTEUiLCJSRU5UT04iKSkgJT4lIAogIGdncGxvdChtYXBwaW5nID0gYWVzKHkgPSByYXRlKjEwMCwgeCA9IFllYXIsIGdyb3VwID0gQ2l0eSwgY29sb3IgPSBDaXR5LCBhbHBoYSA9IENpdHksIHNpemUgPSBDaXR5KSkgKwogIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gIlNlYXR0bGUgaXMgdGhlIG9ubHkgY2l0eSB3aXRoIGNvbnNpc3RlbnQgZ3Jvd2luZyBwZXJjZW50YWdlIG9mIG5vbi12aW9sYXRpbmcgcmVzdGF1cmFudHMgc2luY2UgdGhlIFxuaW50cm9kdWN0aW9uIG9mIG5ldyBzeXN0ZW0gaW4gSmFudWFyeSAyMDE3IiwgeCA9ICIiLCB5ID0gIlBlcmNlbnRhZ2Ugb2Ygbm9uLXZpb2xhdGluZyByZXN0YXVyYW50cyIsIHN1YnRpdGxlID0gc3VidGl0bGUpICsKICBzY2FsZV9hbHBoYV9tYW51YWwodmFsdWVzID0gYygwLjQsMC40LDAuNCwwLjQsMC44KSkgKwogIHNjYWxlX3NpemVfbWFudWFsKHZhbHVlcyA9IGMoMSwxLDEsMSwzKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJkYXJrb3JhbmdlMyIsImNhZGV0Ymx1ZSIsInB1cnBsZTQiLCJ5ZWxsb3c0IiwiZ3JleTI1IikpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gZnVuY3Rpb24oeCkgcGFzdGUwKHgsICclJykpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLCBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG9yID0gImJsYWNrIikpIAoKZ2dzYXZlKCdTZWF0dGxlX25vX3Zpb2xhdGlvbi5wbmcnKQpgYGAKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CnN1YnRpdGxlID0gcGFzdGUwKCJJbiBTZWF0dGxlLCByZXN0YXVyYW50cyB3aXRoIHJlZCB2aW9sYXRpb25zIGRlY2xpbmVkIHRvICIscm91bmQobWVyZ2VkX3JlZFs2MCw1XSoxMDApLCAiJSAsICIscm91bmQobWVyZ2VkX3JlZFs2NSw1XSoxMDApLCAiJSAgYW5kICIscm91bmQobWVyZ2VkX3JlZFs3MCw1XSoxMDApLCAiJSBpbiAyMDE3LCAyMDE4IGFuZCAyMDE5LCByZXNwZWN0aXZlbHkiKSAKCm1lcmdlZF9yZWQgJT4lIAogIGZpbHRlcihDaXR5ICVpbiUgYygiQkVMTEVWVUUiLCJLRU5UIiwiRkVERVJBTCBXQVkiLCJTRUFUVExFIiwiUkVOVE9OIikpICU+JSAKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh5ID0gcmF0ZSoxMDAsIHggPSBZZWFyLCBncm91cCA9IENpdHksIGNvbG9yID0gQ2l0eSwgYWxwaGEgPSBDaXR5LCBzaXplID0gQ2l0eSkpICsKICBnZW9tX2xpbmUoKSArCiAgbGFicyh0aXRsZSA9ICJTZWF0dGxlIGlzIHRoZSBvbmx5IGNpdHkgd2l0aCBjb25zaXN0ZW50IGRlY2xpbmluZyBwZXJjZW50YWdlIG9mIHJlZCB2aW9sYXRpb24gcmVzdGF1cmFudHMgc2luY2UgdGhlIFxuaW50cm9kdWN0aW9uIG9mIG5ldyBzeXN0ZW0gaW4gSmFudWFyeSAyMDE3Iiwgc3VidGl0bGUgPSBzdWJ0aXRsZSwgeCA9ICIiLCB5ID0gIlBlcmNlbnRhZ2Ugb2YgcmVkIHZpb2xhdGlvbiByZXN0YXVyYW50cyIpICsgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGZ1bmN0aW9uKHgpIHBhc3RlMCh4LCAnJScpKSArCiAgc2NhbGVfYWxwaGFfbWFudWFsKHZhbHVlcyA9IGMoMC40LDAuNCwwLjQsMC40LDAuOCkpICsKICBzY2FsZV9zaXplX21hbnVhbCh2YWx1ZXMgPSBjKDEsMSwxLDEsMykpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiZGFya29yYW5nZTMiLCJjYWRldGJsdWUiLCJwdXJwbGU0IiwieWVsbG93NCIsImdyZXkyNSIpKSArCiAgI3NjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50KSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSksIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiYmxhY2siKSwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQoKZ2dzYXZlKCdTZWF0dGxlX25vX3JlZF92aW9sYXRpb24ucG5nJykKYGBgCgojIyBUaGUgbWVkaWFuIGluc3BlY3Rpb24gc2NvcmUgb2YgdmlvbGF0aW5nIHJlc3RhdXJhbnRzIGhhdmUgZGVjbGluZWQgc2luY2UgdGhlIGludHJvZHVjdGlvbiBvZiBuZXcgcmF0aW5nIHN5c3RlbSBpbiAyMDE3CgpBcyB3ZSBzYXcgZWFybGllciBpbiB0aGlzIGRvY3VtZW50IHNpbmNlIGluc3BlY3Rpb24gc2NvcmUgaXMgYSBza2V3ZWQgbWVhc3VyZSB3ZSBzaG91bGQgdXNlIHRoZSBtZWRpYW4gaW5zdGVhZCBvZiB0aGUgbWVhbi4gVG8gdGVzdCBpZiB0aGUgbWVkaWFucyBhcmUgZGlmZmVyZW50IHdlIHdpbGwgdXRpbGl6ZSB0aGUgTW9vZOKAmXMgbWVkaWFuIHRlc3QuICAgCk5vdGU6IEZvciB0ZXN0aW5nIHRoZSBzaWduaWZpY2FuY2UsIEkgaGF2ZSB1c2VkIHRoZSBkYXRhIHNpbmNlIDIwMTQgYmVjYXVzZSB0aGF0IGlzIHdoZW4gZm9vZCBib3JuZSBpbGxuZXNzIG91dGJyZWFrIGhhcHBlbmVkIHdoaWNoIGxlZCB0byB0aGUgaWRlYSBvZiB0aGUgbmV3IHJhdGluZyBzeXN0ZW0KCmBgYHtyIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9Cm1lZGlhbl90ZXN0IDwtIGluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JQogIGZpbHRlcihJbnNwZWN0aW9uX1Njb3JlICE9IDApICU+JSAKICBmaWx0ZXIoWWVhciAlaW4lIGMoJzIwMTQnLCcyMDE1JywnMjAxNicsJzIwMTcnLCcyMDE4JywnMjAxOScpKSAlPiUgCiAgbXV0YXRlKFllYXIgPSBhcy5mYWN0b3IoWWVhcikpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCgpQVCA9IHBhaXJ3aXNlTWVkaWFuTWF0cml4KEluc3BlY3Rpb25fU2NvcmUgfiBZZWFyLAogICAgICAgICAgICAgICAgICAgICAgICBkYXRhICAgPSBtZWRpYW5fdGVzdCwKICAgICAgICAgICAgICAgICAgICAgICAgZXhhY3QgID0gTlVMTCwKICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gImJvbmZlcnJvbmkiKQoKa2FibGUoUFQkQWRqdXN0ZWQpICU+JSBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgZnVsbF93aWR0aCA9IFQpCmBgYAoKIC0gV2UgY2FuIGNvbmNsdWRlIChhdCA5NSUgY29uZmlkZW5jZSBsZXZlbCkgdGhhdCBtZWRpYW4gaW5zcGVjdGlvbiBzY29yZXMgaW4gMjAxNCwgMjAxNSBhbmQgMjAxNiBhcmUgc3RhdGlzdGljYWxseSBkaWZmZXJlbnQgZnJvbSAyMDE3LCAyMDE4IGFuZCAyMDE5IGFmdGVyIHRoZSBpbnRyb2R1Y3Rpb24gb2YgbmV3IHJhdGluZyBzeXN0ZW0gaW4gMjAxNyAgCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQptZWRpYW5faW5zcGVjdGlvbl9zY29yZSA8LSBpbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUKICBmaWx0ZXIoSW5zcGVjdGlvbl9TY29yZSAhPSAwKSAlPiUKICBncm91cF9ieShZZWFyKSAlPiUKICBzdW1tYXJpc2Uoc2NvcmUgPSBtZWRpYW4oSW5zcGVjdGlvbl9TY29yZSkpIAoKc3VidGl0bGUgPSBwYXN0ZTAoIkFmdGVyIHRoZSBpbnRyb2R1Y3Rpb24gb2YgdGhlIG5ldyByYXRpbmcgc3lzdGVtIGluIDIwMTcsIHRoZXJlIHdhcyBhIGRlY2xpbmUgb2YgIiwgcm91bmQoKG1lZGlhbl9pbnNwZWN0aW9uX3Njb3JlJHNjb3JlWzExXSAtIG1lZGlhbl9pbnNwZWN0aW9uX3Njb3JlJHNjb3JlWzEyXSkvbWVkaWFuX2luc3BlY3Rpb25fc2NvcmUkc2NvcmVbMTFdKjEwMCwyKSwgIiUgbWVkaWFuIGluc3BlY3Rpb24gc2NvcmUiKQoKbWVkaWFuX2luc3BlY3Rpb25fc2NvcmUgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeSA9IHNjb3JlLCB4ID0gWWVhciwgZ3JvdXAgPSAxKSkgKwogIGdlb21fbGluZSgpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSA5LCBsaW5ldHlwZT0iZG90dGVkIiwgY29sb3IgPSAiZGFyayBncmV5Iiwgc2l6ZT0xKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMTIsIGxpbmV0eXBlPSJkb3R0ZWQiLCBjb2xvciA9ICJkYXJrIGdyZXkiLCBzaXplPTEpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGMoJzIwMDYnOicyMDE5JykpICsKICBsYWJzKHRpdGxlID0gIk5ldyByYXRpbmcgc3lzdGVtIGlzIGxlYWRpbmcgdG8gYmV0dGVyIGluc3BlY3Rpb24gc2NvcmVzIixzdWJ0aXRsZSA9IHN1YnRpdGxlICwgeSA9ICJNZWRpYW4gSW5zcGVjdGlvbiBTY29yZSIsIHggPSIiKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gNy45LCB5ID0gMTQuNiwgbGFiZWwgPSAiRm9vZCBCb3JuZSBcbklsbG5lc3MgT3V0YnJlYWsiLCBzaXplID0gMywgY29sb3IgPSJkYXJrIGdyZXkiKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMTIuOCwgeSA9IDE0LjYsIGxhYmVsID0gIk5ldyBSYXRpbmcgXG5TeXN0ZW0iLCBzaXplID0gMywgY29sb3IgPSAKICAgICAgICAgICAgICJkYXJrIGdyZXkiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpICxwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSksIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJibGFjayIpLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpCgpnZ3NhdmUoJ2luc3BlY3Rpb25fc2NvcmUucG5nJykKYGBgCgojIyBUaGUgbWVkaWFuIGluc3BlY3Rpb24gc2NvcmUgb2YgdmlvbGF0aW5nIHJlc3RhdXJhbnRzIGRlY2xpbmVkIG9ubHkgaW4gU2VhdHRsZSAmIFJlbnRvbiBzaW5jZSB0aGUgaW50cm9kdWN0aW9uIG9mIG5ldyByYXRpbmcgc3lzdGVtIGluIDIwMTcKCkFzIHdlIHNhdyBlYXJsaWVyIGluIHRoaXMgZG9jdW1lbnQgc2luY2UgaW5zcGVjdGlvbiBzY29yZSBpcyBhIHNrZXdlZCBtZWFzdXJlIHdlIHNob3VsZCB1c2UgdGhlIG1lZGlhbiBpbnN0ZWFkIG9mIHRoZSBtZWFuLiBUbyB0ZXN0IGlmIHRoZSBtZWRpYW5zIGFyZSBkaWZmZXJlbnQgd2Ugd2lsbCB1dGlsaXplIHRoZSBNb29k4oCZcyBtZWRpYW4gdGVzdC4gICAKTm90ZTogRm9yIHRlc3RpbmcgdGhlIHNpZ25pZmljYW5jZSwgSSBoYXZlIHVzZWQgdGhlIGRhdGEgc2luY2UgMjAxNCBiZWNhdXNlIHRoYXQgaXMgd2hlbiBmb29kIGJvcm5lIGlsbG5lc3Mgb3V0YnJlYWsgaGFwcGVuZWQgd2hpY2ggbGVkIHRvIHRoZSBpZGVhIG9mIHRoZSBuZXcgcmF0aW5nIHN5c3RlbQoKU0VBVFRMRQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQoKbWVkaWFuX3Rlc3Rfc2VhdHRsZSA8LSBpbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUKICBmaWx0ZXIoQ2l0eSA9PSAiU0VBVFRMRSIpICU+JSAKICBmaWx0ZXIoSW5zcGVjdGlvbl9TY29yZSAhPSAwKSAlPiUgCiAgZmlsdGVyKFllYXIgJWluJSBjKCcyMDE0JywnMjAxNScsJzIwMTYnLCcyMDE3JywnMjAxOCcsJzIwMTknKSkgJT4lIAogIG11dGF0ZShZZWFyID0gYXMuZmFjdG9yKFllYXIpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAoKUFQgPSBwYWlyd2lzZU1lZGlhbk1hdHJpeChJbnNwZWN0aW9uX1Njb3JlIH4gWWVhciwKICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSAgID0gbWVkaWFuX3Rlc3Rfc2VhdHRsZSwKICAgICAgICAgICAgICAgICAgICAgICAgZXhhY3QgID0gTlVMTCwKICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gImJvbmZlcnJvbmkiKQoKa2FibGUoUFQkQWRqdXN0ZWQpICU+JSBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgZnVsbF93aWR0aCA9IFQpCmBgYAoKQkVMTEVWVUUKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KCm1lZGlhbl90ZXN0X2JlbGwgPC0gaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lCiAgZmlsdGVyKENpdHkgPT0gIkJFTExFVlVFIikgJT4lIAogIGZpbHRlcihJbnNwZWN0aW9uX1Njb3JlICE9IDApICU+JSAKICBmaWx0ZXIoWWVhciAlaW4lIGMoJzIwMTQnLCcyMDE1JywnMjAxNicsJzIwMTcnLCcyMDE4JywnMjAxOScpKSAlPiUgCiAgbXV0YXRlKFllYXIgPSBhcy5mYWN0b3IoWWVhcikpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCgpQVCA9IHBhaXJ3aXNlTWVkaWFuTWF0cml4KEluc3BlY3Rpb25fU2NvcmUgfiBZZWFyLAogICAgICAgICAgICAgICAgICAgICAgICBkYXRhICAgPSBtZWRpYW5fdGVzdF9iZWxsLAogICAgICAgICAgICAgICAgICAgICAgICBleGFjdCAgPSBOVUxMLAogICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiYm9uZmVycm9uaSIpCgprYWJsZShQVCRBZGp1c3RlZCkgJT4lIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gVCkKYGBgCgpGRURFUkFMIFdBWQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQoKbWVkaWFuX3Rlc3RfZmVkIDwtIGluc3BlY3Rpb25fZGF0YV9ub3RfZHVwICU+JQogIGZpbHRlcihDaXR5ID09ICJGRURFUkFMIFdBWSIpICU+JSAKICBmaWx0ZXIoSW5zcGVjdGlvbl9TY29yZSAhPSAwKSAlPiUgCiAgZmlsdGVyKFllYXIgJWluJSBjKCcyMDE0JywnMjAxNScsJzIwMTYnLCcyMDE3JywnMjAxOCcsJzIwMTknKSkgJT4lIAogIG11dGF0ZShZZWFyID0gYXMuZmFjdG9yKFllYXIpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAoKUFQgPSBwYWlyd2lzZU1lZGlhbk1hdHJpeChJbnNwZWN0aW9uX1Njb3JlIH4gWWVhciwKICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSAgID0gbWVkaWFuX3Rlc3RfZmVkLAogICAgICAgICAgICAgICAgICAgICAgICBleGFjdCAgPSBOVUxMLAogICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiYm9uZmVycm9uaSIpCgprYWJsZShQVCRBZGp1c3RlZCkgJT4lIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gVCkKYGBgCgpLRU5UCmBgYHtyIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9Cm1lZGlhbl90ZXN0X2tlbnQgPC0gaW5zcGVjdGlvbl9kYXRhX25vdF9kdXAgJT4lCiAgZmlsdGVyKENpdHkgPT0gIktFTlQiKSAlPiUgCiAgZmlsdGVyKEluc3BlY3Rpb25fU2NvcmUgIT0gMCkgJT4lIAogIGZpbHRlcihZZWFyICVpbiUgYygnMjAxNCcsJzIwMTUnLCcyMDE2JywnMjAxNycsJzIwMTgnLCcyMDE5JykpICU+JSAKICBtdXRhdGUoWWVhciA9IGFzLmZhY3RvcihZZWFyKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKClBUID0gcGFpcndpc2VNZWRpYW5NYXRyaXgoSW5zcGVjdGlvbl9TY29yZSB+IFllYXIsCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgICA9IG1lZGlhbl90ZXN0X2tlbnQsCiAgICAgICAgICAgICAgICAgICAgICAgIGV4YWN0ICA9IE5VTEwsCiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJib25mZXJyb25pIikKCmthYmxlKFBUJEFkanVzdGVkKSAlPiUga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBUKQpgYGAKCgpSRU5UT04KYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KCm1lZGlhbl90ZXN0X3JlbnRvbiA8LSBpbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUKICBmaWx0ZXIoQ2l0eSA9PSAiUkVOVE9OIikgJT4lIAogIGZpbHRlcihJbnNwZWN0aW9uX1Njb3JlICE9IDApICU+JSAKICBmaWx0ZXIoWWVhciAlaW4lIGMoJzIwMTQnLCcyMDE1JywnMjAxNicsJzIwMTcnLCcyMDE4JywnMjAxOScpKSAlPiUgCiAgbXV0YXRlKFllYXIgPSBhcy5mYWN0b3IoWWVhcikpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCgpQVCA9IHBhaXJ3aXNlTWVkaWFuTWF0cml4KEluc3BlY3Rpb25fU2NvcmUgfiBZZWFyLAogICAgICAgICAgICAgICAgICAgICAgICBkYXRhICAgPSBtZWRpYW5fdGVzdF9yZW50b24sCiAgICAgICAgICAgICAgICAgICAgICAgIGV4YWN0ICA9IE5VTEwsCiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJib25mZXJyb25pIikKCmthYmxlKFBUJEFkanVzdGVkKSAlPiUga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBUKQpgYGAKIAogLSBXZSBjYW4gY29uY2x1ZGUgKGF0IDk1JSBjb25maWRlbmNlIGxldmVsKSB0aGF0IG1lZGlhbiBpbnNwZWN0aW9uIHNjb3JlcyBpbiAyMDE0LCAyMDE1IGFuZCAyMDE2IGFyZSBzdGF0aXN0aWNhbGx5IGRpZmZlcmVudCBmcm9tIDIwMTcsIDIwMTggYW5kIDIwMTkgYWZ0ZXIgdGhlIGludHJvZHVjdGlvbiBvZiBuZXcgcmF0aW5nIHN5c3RlbSBpbiAyMDE3IG9ubHkgaW4gU2VhdHRsZQogCmBgYHtyfQojQ2l0eXdpc2UgbWVkaWFuIGluc3BlY3Rpb24gc2NvcmUKCm1lZGlhbl9pbnNwZWN0aW9uX3Njb3JlX2NpdGllcyA8LSBpbnNwZWN0aW9uX2RhdGFfbm90X2R1cCAlPiUgCiAgZmlsdGVyKENpdHkgJWluJSBjKCJCRUxMRVZVRSIsIktFTlQiLCJGRURFUkFMIFdBWSIsIlNFQVRUTEUiLCJSRU5UT04iKSkgJT4lIAogIGZpbHRlcihJbnNwZWN0aW9uX1Njb3JlICE9IDApICU+JSAKICBncm91cF9ieShZZWFyLCBDaXR5KSAlPiUgCiAgc3VtbWFyaXNlKHNjb3JlID0gbWVkaWFuKEluc3BlY3Rpb25fU2NvcmUpKQoKc3VidGl0bGUgPSBwYXN0ZTAoIk1lZGlhbiBpbnNwZWN0aW9uIHNjb3JlIG9mIEJlbGxldnVlIGhhcyBiZWVuICIsIG1lZGlhbl9pbnNwZWN0aW9uX3Njb3JlX2NpdGllc1s2NiwzXSwgIiBpbiAyMDE4IGFuZCAyMDE5IHdoZW4gdGhlIG90aGVyIGNpdGllcyB3ZXJlIGF0ICIsIG1lZGlhbl9pbnNwZWN0aW9uX3Njb3JlX2NpdGllc1s3MCwzXSkKCiAgCiBtZWRpYW5faW5zcGVjdGlvbl9zY29yZV9jaXRpZXMgJT4lIAogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBZZWFyLCB5ID0gc2NvcmUsIGdyb3VwID0gQ2l0eSwgY29sb3IgPSBDaXR5LCBhbHBoYSA9IENpdHksIHNpemUgPSBDaXR5KSkgKyAKICBnZW9tX2xpbmUoKSArCiAgbGFicyh0aXRsZSA9ICJNZWRpYW4gSW5zcGVjdGlvbiBzY29yZSBvZiBhbGwgdGhlIGNpdGllcyBpcyBub3cgdGhlIHNhbWUgZXhjZXB0IEJlbGxldnVlIiwgc3VidGl0bGUgPSBzdWJ0aXRsZSwgeSA9ICJNZWRpYW4gSW5zcGVjdGlvbiBTY29yZSIpICsKICBzY2FsZV9hbHBoYV9tYW51YWwodmFsdWVzID0gYygwLjYsMC40LDAuNCwwLjQsMC42KSkgKwogIHNjYWxlX3NpemVfbWFudWFsKHZhbHVlcyA9IGMoMywyLDEsMSwxKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJkYXJrb3JhbmdlMyIsImNhZGV0Ymx1ZSIsInB1cnBsZTQiLCJ5ZWxsb3c0IiwiZ3JleTI1IikpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLCBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIscGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG9yID0gImJsYWNrIiksIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkgCiAKZ2dzYXZlKCdpbnNwZWN0aW9uX3Njb3JlX2NpdGllcy5wbmcnKSAKYGBg